I am curious about the relationship between Event Loop and Promise.
The demo exposes the question. I expected the p1 fulfilled
appear in the middle, since they queue a task to the same task queue and are executed one by one.
var p1 = new Promise(function(resolve, reject){
resolve(1)
})
setTimeout(function(){
console.log("will be executed at the top of the next Event Loop")
},0)
p1.then(function(value){
console.log("p1 fulfilled")
})
setTimeout(function(){
console.log("will be executed at the bottom of the next Event Loop")
},0)
The console result is:
p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop
The visualized effect shows the promise.then
's callback didn't go to the task queue of the Event Loop. It's right?
【NOTE: The question is not the same as Promise vs setTimeout, since it focus more on the relationship between Event Loop and Promise】
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:
Promise
,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:
In your example:
new Promise
and resolve
are synchronous;setTimeout
macroTask into the macrotask queue;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
;setTimeout
to macrotask queue;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
setTimeout
to macrotask queue, and a microtask promise.then()
to the microtask queue;