Each event loop has a microtask queue and a macrotask queue.
A microtask is a task that is originally to be queued on the microtask queue rather than a task queue. Refer to https://www.w3.org/TR/html51/webappapis.html#microtask-queue.
There are two kinds of microtasks:
- solitary callback microtasks, such as
Promise
,
- and compound microtasks, such as
Object.observe
, MutationObserver
and process.nextTick
in Node.js.
And the macrotask queue mainly contains setTimeout
, setInterval
, setImmediate
, requestAnimationFrame
, I/O
in Nodejs.
In a event Loop, these two task queues will run in two steps:
- First, check whether there is a macrotask (called it X) in old macrotask queue ;
- If X exists and it is running, wait for gotoing the next step until it was complete; otherwise, goto the next step immediately;
- Second, run all microtasks of the microtask queue;
- and when run the microtasks, we can still add some more microtaks into the queue, these tasks will also run.
In your example:
- First, your Promise initialize
new Promise
and resolve
are synchronous;
- and then synchronously add a
setTimeout
macroTask into the macrotask queue;
- then synchronously add the microtask
promise.then(function(){})
to the microtask queue, this task will run immediately, because the Promise initialize and resolve are synchronous, this task run before any macrotask; so, console.log the p1 fulfilled
;
- then add the second macrotask
setTimeout
to macrotask queue;
- after this event loop ended, run the two macrotasks;
for this code:
setTimeout(function(){
console.log("will be executed at the top of the next Event Loop")
},0)
var p1 = new Promise(function(resolve, reject){
setTimeout(function(){resolve(1)},0)
});
setTimeout(function(){
console.log("will be executed at the bottom of the next Event Loop")
},0)
for (var i = 0; i < 100; i++) {
(function(j){
p1.then(function(value){
console.log("promise then - " + j)
});
})(i)
}
the output order:
will be executed at the top of the next Event Loop
promise then - 0
promise then - 1
promise then - 2
...
promise then - 99
will be executed at the bottom of the next Event Loop
- First add three macrotask
setTimeout
to macrotask queue, and a microtask promise.then()
to the microtask queue;
- run a macrotask;
- If condition true run all microtasks, but it's false, so go to the next step;
- run the second macrotask;
- check whether the promise resolved or not, the condition is true, then run all microtasks;
- go on to run other macrotasks;