Promise执行流程与事件循环、宏/微任务队列相关疑问
Event Loop 相关问题解答
问题1:调用setTimeout(callback, time).then(anotherCallback)时,callback和anotherCallback会被推入哪些队列?
首先要明确:setTimeout返回的是数字类型的定时器ID,并非Promise对象,直接链式调用.then(anotherCallback)属于语法错误,这个写法本身不成立。
如果是要实现“等待定时器完成后执行后续回调”的逻辑,正确写法是把setTimeout包裹进Promise:
new Promise((resolve) => { setTimeout(() => { callback(); resolve(); }, time); }).then(anotherCallback);
这种情况下:
callback会在定时器到期后被推入宏任务(macro-task)队列,等待Event Loop调度执行;- 当
resolve()执行后,anotherCallback会被推入微任务(micro-task)队列,优先级高于宏任务,会在当前宏任务执行完毕、下一个宏任务启动前被处理。
问题2:分析给定Promise代码的执行流程,明确最后一个.then的执行时机
先看目标代码:
Promise.resolve() .then(() => { setTimeout(() => alert("timeout"), 0); }) .then(() => { alert("promise"); });
完整执行流程如下:
- 同步代码阶段:执行
Promise.resolve(),该Promise立即进入已完成状态,第一个.then的回调被加入微任务队列。 - 同步代码执行完毕,开始处理微任务队列:
- 取出第一个
.then的回调执行:内部调用setTimeout,WebAPI启动定时器(0秒后触发),定时器到期后,alert("timeout")会被推入宏任务队列。 - 第一个
.then的回调执行完毕,默认返回undefined(等价于Promise.resolve(undefined)),因此第二个.then的回调被加入微任务队列。
- 取出第一个
- 继续处理微任务队列:此时队列中存在第二个
.then的回调,立即执行它,弹出"promise"。 - 微任务队列清空,开始处理宏任务队列:取出
setTimeout的回调执行,弹出"timeout"。
简单总结:最后一个.then的回调是在第一个.then的回调执行完成后,被加入微任务队列并立即执行的,优先级远高于setTimeout对应的宏任务,因此会先弹出"promise",再弹出"timeout"。
内容的提问来源于stack exchange,提问作者Pricey
相关产品推荐
相关产品推荐

