如何预测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的回调执行顺序由以下规则决定:
- 同步代码执行阶段,所有已resolved/rejected的Promise的
then/catch/finally回调会按同步代码的执行顺序被依次加入微任务队列的末尾。 - 微任务队列的处理是「单任务执行」模式:每次只取出队列头部的一个微任务执行,执行完成后,若当前任务触发了新的Promise状态变更(比如
then回调执行完返回默认的undefined,会让后续then关联的Promise变为resolved),则将新的then回调追加到微任务队列的末尾。 - 重复步骤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
相关产品推荐
相关产品推荐

