关于Promise执行顺序的疑问:为何输出顺序为0 1 2 3 4 5 6?
JavaScript事件循环:Promise链式调用的执行顺序解析
问题代码
Promise.resolve() .then(() => { console.log(0) return Promise.resolve(4) }) .then(res => { console.log(res) }) Promise.resolve() .then(() => { console.log(1) }) .then(() => { console.log(2) }) .then(() => { console.log(3) }) .then(() => { console.log(5) }) .then(() => { console.log(6) })
输出结果
0 1 2 3 4 5 6
执行顺序解析
核心要搞清楚微任务队列的调度规则:Promise的then回调会被加入微任务队列,事件循环会先清空当前微任务队列,再处理下一轮微任务,同一轮队列中的任务按添加顺序执行。我们一步步拆解流程:
初始化阶段
两个Promise.resolve()生成已完成状态的Promise,它们的第一个then回调被加入初始微任务队列(记为MQ1),此时队列内容:[打印0的回调, 打印1的回调]处理MQ1队列
- 先执行「打印0的回调」:输出
0,随后返回Promise.resolve(4)。这里的关键是:返回已完成的Promise时,当前Promise链的下一个then(打印4的回调)不会直接加入当前队列,而是要等这个返回Promise的内部resolve逻辑触发微任务后,才会被加入后续的队列。 - 接着执行「打印1的回调」:输出
1,它的下一个then(打印2的回调)被加入MQ1末尾,此时MQ1变为[打印2的回调]
- 先执行「打印0的回调」:输出
处理下一轮微任务队列(MQ2)
- 执行「打印2的回调」:输出
2,下一个then(打印3的回调)被加入MQ2末尾,队列变为[打印3的回调] - 执行「打印3的回调」:输出
3,下一个then(打印5的回调)被加入MQ2末尾,队列变为[打印5的回调] - 此时,之前返回的
Promise.resolve(4)的内部微任务触发,将「打印4的回调」加入MQ2末尾,队列变为[打印5的回调, 打印4的回调]
- 执行「打印2的回调」:输出
继续处理MQ2队列
- 先执行「打印4的回调」:输出
4 - 再执行「打印5的回调」:输出
5,下一个then(打印6的回调)被加入新的微任务队列(MQ3)
- 先执行「打印4的回调」:输出
处理MQ3队列
- 执行「打印6的回调」:输出
6
- 执行「打印6的回调」:输出
关键疑问解答:为什么Promise.resolve(4)的回调是第5个执行?
因为在then回调中返回Promise.resolve(4)时,这个操作会多触发一次微任务调度——浏览器需要先处理这个返回Promise的内部resolve逻辑,才会把对应的then回调(打印4)加入队列。而在这个等待过程中,第二个Promise链的「打印2、打印3」回调已经依次执行并把后续回调加入队列,所以打印4的回调会排在打印3之后、打印5之前,最终成为第5个输出的内容。
内容的提问来源于stack exchange,提问作者Zerok
相关产品推荐
相关产品推荐

