我们知道承诺是微任务,它们被添加到微任务队列中,事件侦听器/计时器是任务,因此它们被添加到任务队列中。但是,如果事件侦听器/计时器位于 promise 函数内部(该函数在创建 promise to promise 构造函数时传递(,那么它们呢?它们被添加到哪个队列中?
console.log("script start");
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("setTimeout2");
resolve();
}, 0);
});
promise.then(function () {
console.log("promise2");
});
setTimeout(function () {
console.log("setTimeout");
}, 0);
console.log("script end");
这里的"脚本启动"是主任务的一部分,因此它被执行/打印。
然后将 promise 的回调函数处理给浏览器,处理程序将其添加到微任务队列中。
then(( 将回调传递给浏览器的处理程序,它将在解决主承诺后执行。
承诺之外的 setTimeout 将添加到任务队列中。
打印"脚本结束"。
现在微任务队列上有一个微任务,任务队列上有一个任务。
因此,微任务将首先执行,因为它们的优先级高于任务。
但是在任务内部,有一个计时器。
我们知道计时器已添加到任务队列中。但在这里我认为计时器被添加到微任务队列中。因为如果它被添加到任务队列中,那么"setTimeout2"将在稍后打印,因为在任务队列上已经有一个打印"setTimeout"的任务。 那么那里到底发生了什么?
"在承诺中"没有什么特别之处。放在微任务队列中的唯一函数是传递给then
的回调。
以下是实际发生的情况:
- 执行
script start
日志 - 创建承诺并调用其执行器回调。执行器回调调用
setTimeout
,这会调度计时器。 - 承诺被分配给
promise
变量 - 调用
then()
方法并将履行回调附加到承诺 - 调用第二个
setTimeout
并计划第二个计时器 - 执行
script end
日志
这一切都在一个任务执行中同步发生。一段时间后,计时器触发并(只有这样!(将其(宏(任务添加到计时器事件队列中。浏览器处理第一个:
- 执行
setTimeout2
日志 - 执行
resolve()
函数,该函数履行承诺并添加作业以运行履行回调到微任务队列
完成此宏任务后,将处理微任务队列中的任务:
- 执行
promise2
日志
由于微任务队列已经是空的,因此可以处理下一个宏任务:
- 执行
setTimeout
日志