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

如何预测Promise.then链中的微任务执行顺序?代码示例答疑

Promise.then链的微任务执行顺序规则解析

先看你给出的代码示例:

Promise.resolve()
    .then(() => console.log("Microtask 1"))
    .then(() => console.log("Microtask 11"));

Promise.resolve()
    .then(() => console.log("Microtask 2"))
    .then(() => console.log("Microtask 22"))

实际输出是:

Microtask 1
Microtask 2
Microtask 11
Microtask 22

核心规则:微任务队列的「逐个执行+动态追加」机制

JavaScript引擎处理任务时,遵循同步代码优先,微任务队列逐个执行的原则,Promise.then的回调执行顺序由以下规则决定:

  1. 同步代码执行阶段,所有已resolved/rejected的Promise的then/catch/finally回调会按同步代码的执行顺序被依次加入微任务队列的末尾。
  2. 微任务队列的处理是「单任务执行」模式:每次只取出队列头部的一个微任务执行,执行完成后,若当前任务触发了新的Promise状态变更(比如then回调执行完返回默认的undefined,会让后续then关联的Promise变为resolved),则将新的then回调追加到微任务队列的末尾。
  3. 重复步骤2,直到微任务队列为空。

针对示例代码的分步拆解

1. 同步代码执行阶段

  • 执行第一个Promise.resolve(),生成已resolved的Promise,调用.then(() => console.log("Microtask 1")),这个回调被加入微任务队列,此时队列:[Microtask 1]
  • 执行第二个Promise.resolve(),生成已resolved的Promise,调用.then(() => console.log("Microtask 2")),这个回调被追加到队列末尾,此时队列:[Microtask 1, Microtask 2]

2. 微任务队列处理阶段

  • 取出队列第一个任务:执行Microtask 1,输出Microtask 1。该回调执行完返回undefined,导致后续.then(() => console.log("Microtask 11"))关联的Promise变为resolved,这个新回调被追加到队列末尾,此时队列:[Microtask 2, Microtask 11]
  • 取出队列下一个任务:执行Microtask 2,输出Microtask 2。同理,后续.then(() => console.log("Microtask 22"))的回调被追加到队列末尾,此时队列:[Microtask 11, Microtask 22]
  • 取出队列第一个任务:执行Microtask 11,输出Microtask 11,无后续回调,队列变为:[Microtask 22]
  • 取出队列最后一个任务:执行Microtask 22,输出Microtask 22,队列清空。

如何预测Promise.then链的执行顺序?

按以下步骤梳理即可:

  • 第一步:标记初始微任务:先执行所有同步代码,把所有立即进入resolved/rejected状态的Promise的第一个then/catch/finally回调,按同步代码的执行顺序加入微任务队列。
  • 第二步:逐个处理微任务:每次取出队列头部的任务执行,执行完成后,检查该任务是否触发了新的Promise状态变更(比如then回调执行完毕),如果有,将对应的后续then回调追加到队列末尾。
  • 第三步:循环处理:重复第二步,直到微任务队列被清空。

关键提醒:不要误以为整个then链会被一次性加入队列,实际上每个then回调都是在前一个回调执行完成、对应的Promise状态变更后,才会被加入微任务队列。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:50:36