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

Promise Microtask Queue执行顺序疑问:为何输出与预期不符?

两段Promise代码输出差异的原因解析

代码示例与输出差异

第一段代码执行后输出为 10, 1:

const p1 = new Promise((_, reject) => {
  reject(1);  
}).then((r)=>console.log(r)).catch((r)=>console.log(r)); 

const p2 = new Promise((resolve, _) => {
  resolve(10);  
}).then((r)=>console.log(r)).catch((r)=>console.log(r));

第二段代码执行后输出为 1, 10:

const p1 = new Promise((_, reject) => {
  reject(1);  
}).catch((r)=>console.log(r))

const p2 = new Promise((resolve, _) => {
  resolve(10);  
}).then((r)=>console.log(r)).catch((r)=>console.log(r));

疑问

按逻辑,p1的catch回调应早于p2的then回调被加入微任务队列,输出应为1, 10才对,为何第一段代码输出相反?

原因解释

核心在于Promise链式调用中,每个.then或.catch都会返回一个新的Promise,微任务的添加时机是当前链式调用中前一个Promise的状态确定之后。

第一段代码的执行流程

  • p1的执行链:
    1. 初始Promise立即reject(1),状态变为rejected。
    2. 调用.then((r)=>console.log(r)):由于原Promise是rejected状态,这个then的回调会被直接跳过,同时该then返回一个新的Promise,状态也变为rejected,值为1。
    3. 只有当这个then返回的新Promise状态确定为rejected后,后续的.catch回调才会被加入微任务队列。
  • p2的执行链:
    1. 初始Promise立即resolve(10),状态变为fulfilled。
    2. 调用.then((r)=>console.log(r)):由于原Promise已经是fulfilled状态,这个then的回调会直接被加入微任务队列。

所以在第一段代码中,p2的then回调比p1的catch回调更早进入微任务队列,因此先输出10,再输出1。

第二段代码的执行流程

  • p1的执行链:
    初始Promise立即reject(1),状态变为rejected,后续的.catch回调直接被加入微任务队列(没有中间的.then环节)。
  • p2的执行链:和第一段一致,then回调被加入微任务队列,但晚于p1的catch回调。

因此第二段代码中p1的catch先执行,输出1,再输出10。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:08:20