我很好奇Event Loop和Promise之间的关系
该演示揭示了这个问题。我期望p1 fulfilled
出现在中间,,因为他们将任务排队到同一个任务队列并逐个执行。
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
The visualized effect显示promise.then
的回调没有进入事件循环的任务队列。这是对的吗?
【注意:问题与Promise vs setTimeout不一样,因为它更关注事件循环和承诺之间的关系】
答案 0 :(得分:12)
每个事件循环都有一个微任务队列和一个macrotask队列。
微任务是最初要在微任务队列而不是任务队列上排队的任务。请参阅https://www.w3.org/TR/html51/webappapis.html#microtask-queue。
有两种微任务:
Promise
,Object.observe
,MutationObserver
和process.nextTick
。 macrotask队列主要包含Nodejs中的setTimeout
,setInterval
,setImmediate
,requestAnimationFrame
,I/O
。
在事件循环中,这两个任务队列将分两步运行:
在你的例子中:
new Promise
和resolve
是同步的; setTimeout
macroTask同步添加到macrotask队列中; promise.then(function(){})
添加到微任务队列,此任务将立即运行,因为Promise初始化和解析是同步的,此任务在任何macrotask之前运行;所以,console.log p1 fulfilled
; setTimeout
添加到macrotask队列; 代码:
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
添加到macrotask队列,将微任务promise.then()
添加到微任务队列; 答案 1 :(得分:0)
...... Promises / A +规范要求 始终使用后一种执行模式。它通过这样说明 对于then()方法遵循requirement(2.2.4):
在执行之前,不得调用onPulfilled或onRejected 上下文堆栈仅包含平台代码。
重要的是要注意:
这意味着你的代码可以依赖于run-to-completion语义(如 在第1部分中解释,并且链接承诺不会使其他人挨饿 处理时间的任务。