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

return Promise.resolve()对JavaScript事件循环的影响及执行顺序疑问

为什么Promise.resolve().then()会让输出变成3 2 1?

嘿,这个问题其实戳中了JavaScript事件循环里**宏任务(macrotasks)和微任务(microtasks)**的优先级差异,很多刚深入事件循环的开发者都会在这里踩坑,我来给你掰扯清楚:

首先,先把你的代码拆解成执行步骤,一步步看:

setTimeout(()=> console.log('1')); // 这是一个宏任务
Promise.resolve('whatever').then(()=>console.log('2')); // 这是一个微任务
console.log('3'); // 同步代码

执行顺序的核心逻辑:

JavaScript的事件循环遵循「先同步,再微任务,最后宏任务」的优先级:

  1. 先执行所有同步代码:
    代码从上到下走,console.log('3')是同步任务,会立即执行,所以先输出3。

  2. 同步代码执行完后,清空当前微任务队列:
    同步执行栈空了之后,事件循环会先检查微任务队列里有没有等待执行的任务。Promise.resolve().then()的回调就属于微任务,它会被加入微任务队列,这时候会立即执行这个回调,输出2。

  3. 微任务队列清空后,才会执行宏任务队列里的任务:
    等所有微任务都处理完,事件循环才会去看宏任务队列。setTimeout的回调是宏任务,这时候才会被执行,输出1。

为什么你之前预期错了?

你可能误以为Promise.resolve().then()和setTimeout是同级的任务,但实际上它们分属不同的任务队列:

  • 宏任务队列:存放setTimeout、setInterval、I/O操作、UI渲染这类任务,每次事件循环只取一个宏任务执行。
  • 微任务队列:存放Promise的then/catch/finally、MutationObserver、Node.js里的process.nextTick这类任务,每次执行完同步代码或一个宏任务后,会把整个微任务队列清空才会继续。

简单说就是:微任务的优先级比宏任务高,会插队在宏任务前面执行。

如果把你的代码稍微改一下,多加几个微任务和宏任务,你就能更清楚看到这个规律:

setTimeout(() => console.log('宏任务1'));
Promise.resolve().then(() => {
  console.log('微任务1');
  Promise.resolve().then(() => console.log('微任务2'));
});
setTimeout(() => console.log('宏任务2'));
console.log('同步代码');

输出会是:同步代码 → 微任务1 → 微任务2 → 宏任务1 → 宏任务2,完美验证了微任务队列会被一次性清空的规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:16:42