我很好奇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
可视化效果 http://latentflip.com/loupe/?code=dmFyIHAxID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXsKICAgIHJlc29sdmUoMSkKfSk7CnNldFRpbWVvdXQoZnVuY3Rpb24oKXsKICBjb25zb2xlLmxvZygid2lsbCBiZSBleGVjdXRlZCBhdCB0aGUgdG9wIG9mIHRoZSBuZXh0IEV2ZW50IExvb3AiKQp9LDApCnAxLnRoZW4oZnVuY3Rpb24odmFsdWUpewogIGNvbnNvbGUubG9nKCJwMSBmdWxmaWxsZWQiKQp9KQpzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7CiAgY29uc29sZS5sb2coIndpbGwgYmUgZXhlY3V0ZWQgYXQgdGhlIGJvdHRvbSBvZiB0aGUgbmV4dCBFdmVudCBMb29wIikKfSwwKQ%3D%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D显示了promise.then
的回调没有进入事件循环的任务队列。这是正确的?
【注意:这个问题与Promise 与 setTimeout https://stackoverflow.com/questions/38752620/promise-vs-settimeout,因为它更关注Event Loop和Promise之间的关系】
每个事件循环都有一个微任务队列和一个宏任务队列。
微任务是原本要在微任务队列而不是任务队列上排队的任务。参考https://www.w3.org/TR/html51/webappapis.html#microtask-queue https://www.w3.org/TR/html51/webappapis.html#microtask-queue.
微任务有两种:
- 单独的回调微任务,例如
Promise
,
- 和复合微任务,例如
Object.observe
, MutationObserver
and process.nextTick
在 Node.js 中。
而宏任务队列主要包含setTimeout
, setInterval
, setImmediate
, requestAnimationFrame
, I/O
在 Node.js 中。
在事件循环中,这两个任务队列将分两步运行:
- 首先,检查旧的宏任务队列中是否存在宏任务(称之为X);
- 如果X存在并且正在运行,则等待它执行下一步,直到完成;否则,立即进行下一步;
- 其次,运行微任务队列的所有微任务;
- 当运行微任务时,我们仍然可以添加更多的微任务到队列中,这些任务也会运行。
在你的例子中:
- 首先,你的 Promise 初始化
new Promise
and resolve
是同步的;
- 然后同步添加一个
setTimeout
将macroTask放入macrotask队列中;
- 然后同步添加微任务
promise.then(function(){})
到 microtask 队列中,该任务会立即运行,因为 Promise 的初始化和解析是同步的,该任务在任何宏任务之前运行;所以,console.logp1 fulfilled
;
- 然后添加第二个宏任务
setTimeout
到宏任务队列;
- 事件循环结束后,运行两个宏任务;
对于这段代码:
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()
到微任务队列;
- 运行宏任务;
- 如果条件为 true 则运行所有微任务,但为 false,则进入下一步;
- 运行第二个宏任务;
- 检查promise是否已解决,条件为真,然后运行所有微任务;
- 继续运行其他宏任务;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)