We know that JavaScript is single-threaded, meaning it can only do one thing at a time. It's like going through security check at a train station—everyone passes one by one. That's single-threading. But this raises a problem: if there is a slow HTTP request in the program, the user must wait for the response before continuing with subsequent operations, which is not ideal. So we let the program code for long-running requests be suspended, allowing the user to do other things first.
In JavaScript, we divide tasks into synchronous tasks and asynchronous tasks. Let's first look at the execution order of a piece of code.
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
Why is the result like this? Because when a task enters the execution stack, it is first determined whether it is a synchronous task. If it is synchronous, it enters the main thread for execution; if it is asynchronous, it registers a callback function in the event table and places it into the event queue.
-
Synchronous and asynchronous tasks enter different execution "places": synchronous tasks go to the main thread, and asynchronous tasks go to the Event Table and register functions.
-
When the specified event completes, the Event Table moves the function into the Event Queue.
-
When the main thread's tasks are all executed and empty, it will read the corresponding function from the Event Queue and execute it on the main thread.
-
The above process repeats continuously, which is commonly referred to as the Event Loop.
03 Macro Tasks and Micro Tasks
Above we know about synchronous and asynchronous tasks, but how are asynchronous tasks classified? Actually, asynchronous tasks include macro tasks and micro tasks. They are added to the same queue, but the execution order is different.

Macro tasks: overall code script, setTimeout, setInterval, setImmediate
Micro tasks: native Promise's then method, process.nextTick, MutationObserver
For macro tasks and micro tasks, just remember the ones listed above.
Let's focus on understanding the execution process of setTimeout:
setTimeout(() => { task(); },3000) console.log('Execute console');
According to the event loop process, we know that the program executes the print operation first and then executes the timer. But let's slightly modify the function:
1 2 3 4 |
setTimeout(() => { task() },3000) //Assume the synchronous task here takes 10 seconds to execute |
At this point, we find that the task() callback is not executed after 3 seconds, but waits for the 10-second synchronous task to finish before executing task(). Let's analyze:
- task() as an asynchronous task enters the Event Table and registers a callback event, and starts timing.
- Execute the synchronous task.
- After 3 seconds, task() enters the event queue (but task() cannot execute immediately at this point).
- After 10 seconds, task() is taken from the event queue and placed into the main thread for execution.
One more thing to add about setTimeout: even if the main thread is empty, setTimeout(fn, 0) actually cannot achieve 0 milliseconds. According to the HTML standard, the minimum is 4 milliseconds. As for setInterval(fn, ms), it does not execute every ms exactly; instead, after ms, the callback function is added to the event queue, so setInterval may not be accurate.
Finally, here is a comprehensive question:
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
1, 7, 6, 8, 2, 4, 3, 5, 9, 11, 10, 12Details:
http://blog.alanwu.website/2020/03/06/eventLoop/
暂无评论。