事件循环和Promise有什么关系 [英] What is the relationship between event loop and Promise
问题描述
我很好奇Event Loop和Promise的关系.
演示暴露了这个问题.我希望 p1 completed
出现在中间,因为它们将一个任务排到同一个任务队列中并被一个一个地执行.
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)
控制台结果为:
p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop
的可视化效果示出了<代码>promise.then 的回调没有进入 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?
【注意:这个问题与 Promise vs setTimeout 不同,因为它更关注Event Loop和Promise的关系】
【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.
微任务是原本要在微任务队列中排队的任务,而不是任务队列.请参阅 https://www.w3.org/TR/html51/webappapis.html#microtask-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.
有两种微任务:
- 单独回调微任务,例如
Promise
, - 和复合微任务,例如 Node.js 中的
Object.observe
、MutationObserver
和process.nextTick
.
- solitary callback microtasks, such as
Promise
, - and compound microtasks, such as
Object.observe
,MutationObserver
andprocess.nextTick
in Node.js.
而宏任务队列主要包含setTimeout
、setInterval
、setImmediate
、requestAnimationFrame
、I/O
在 Nodejs 中.
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:
- 首先检查旧的宏任务队列中是否有宏任务(称为X);
- 如果X存在并且正在运行,则等待它进入下一步,直到它完成;否则,立即进入下一步;
- 其次,运行微任务队列的所有微任务;
- 当运行微任务时,我们仍然可以将更多的微任务添加到队列中,这些任务也会运行.
在你的例子中:
- 首先,你的Promise初始化
new Promise
和resolve
是同步的; - 然后同步添加一个
setTimeout
宏任务到宏任务队列中; - 然后将微任务
promise.then(function(){})
同步添加到微任务队列中,这个任务会立即运行,因为Promise的初始化和解析是同步的,这个任务在任何之前运行宏任务;所以,console.logp1 已完成
; - 然后将第二个宏任务
setTimeout
添加到宏任务队列中; - 在这个事件循环结束后,运行两个宏任务;
- First, your Promise initialize
new Promise
andresolve
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 thep1 fulfilled
; - then add the second macrotask
setTimeout
to macrotask queue; - after this event loop ended, run the two macrotasks;
对于此代码:
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)
}
输出顺序:
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
添加到宏任务队列,并添加一个微任务promise.then()
到微任务队列; - 运行宏任务;
- 如果条件为真,则运行所有微任务,但为假,则进入下一步;
- 运行第二个宏任务;
- 检查promise是否解决,条件为真,然后运行所有微任务;
- 继续运行其他宏任务;
- First add three macrotask
setTimeout
to macrotask queue, and a microtaskpromise.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;
这篇关于事件循环和Promise有什么关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!