You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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回调会被加入微任务队列,事件循环会先清空当前微任务队列,再处理下一轮微任务,同一轮队列中的任务按添加顺序执行。我们一步步拆解流程:

  1. 初始化阶段
    两个Promise.resolve()生成已完成状态的Promise,它们的第一个then回调被加入初始微任务队列(记为MQ1),此时队列内容:[打印0的回调, 打印1的回调]

  2. 处理MQ1队列

    • 先执行「打印0的回调」:输出0,随后返回Promise.resolve(4)。这里的关键是:返回已完成的Promise时,当前Promise链的下一个then(打印4的回调)不会直接加入当前队列,而是要等这个返回Promise的内部resolve逻辑触发微任务后,才会被加入后续的队列。
    • 接着执行「打印1的回调」:输出1,它的下一个then(打印2的回调)被加入MQ1末尾,此时MQ1变为[打印2的回调]
  3. 处理下一轮微任务队列(MQ2)

    • 执行「打印2的回调」:输出2,下一个then(打印3的回调)被加入MQ2末尾,队列变为[打印3的回调]
    • 执行「打印3的回调」:输出3,下一个then(打印5的回调)被加入MQ2末尾,队列变为[打印5的回调]
    • 此时,之前返回的Promise.resolve(4)的内部微任务触发,将「打印4的回调」加入MQ2末尾,队列变为[打印5的回调, 打印4的回调]
  4. 继续处理MQ2队列

    • 先执行「打印4的回调」:输出4
    • 再执行「打印5的回调」:输出5,下一个then(打印6的回调)被加入新的微任务队列(MQ3)
  5. 处理MQ3队列

    • 执行「打印6的回调」:输出6

关键疑问解答:为什么Promise.resolve(4)的回调是第5个执行?

因为在then回调中返回Promise.resolve(4)时,这个操作会多触发一次微任务调度——浏览器需要先处理这个返回Promise的内部resolve逻辑,才会把对应的then回调(打印4)加入队列。而在这个等待过程中,第二个Promise链的「打印2、打印3」回调已经依次执行并把后续回调加入队列,所以打印4的回调会排在打印3之后、打印5之前,最终成为第5个输出的内容。

内容的提问来源于stack exchange,提问作者Zerok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 20:15:01