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

Promise、async/await、setTimeout优先级疑问:b2输出顺序为何不符预期?

async/await 与 Promise 执行顺序解惑

原代码

async function a() {
  console.log("a");
}
async function b() {
  console.log("b1");
  await a();
  console.log("b2");
}
setTimeout(() => {
  console.log("setTimeout");
}, 0);
b();
new Promise((resolve) => {
  console.log("p1");
  resolve();
}).then(() => {
  console.log("p2");
});
console.log("end");

实际输出

"b1"
"a"
"p1"
"end"
"b2"
"p2"
"setTimeout"

预期输出

"b1"
"a"
"b2"
"p1"
"end"
"p2"
"setTimeout"

核心疑问

理解前两项输出,但不清楚b2为何未在a之后立即输出,反而在p1、end之后才出现。


问题根源:await 的执行逻辑

要理清顺序,得拆解await a()的完整执行步骤:

  1. 调用b()后,先同步执行console.log("b1"),输出b1。
  2. 执行await a()时,先同步调用a(),所以a内部的console.log("a")立即执行,输出a。
  3. a()是async函数,返回一个已resolved的Promise。此时await会将自身之后的代码(console.log("b2"))包装成回调,放入微任务队列,但不会立即执行——主线程此时还在处理剩余的同步代码。

后续执行流程

将b2的回调丢入微任务队列后,主线程继续按顺序执行同步代码:

  • 执行new Promise(...):Promise构造函数是同步执行的,因此先输出p1;调用resolve()后,将then里的console.log("p2")也放入微任务队列。
  • 执行console.log("end"),输出end。

当主线程所有同步代码执行完毕后,才会开始处理微任务队列:

  • 微任务队列此时有两个任务:先是await后续的b2回调,然后是Promise的p2回调。
  • 按顺序执行这两个微任务,依次输出b2和p2。

微任务全部处理完成后,才会触发宏任务队列里的setTimeout回调,输出setTimeout。

为什么预期顺序不成立

你误以为await a()之后会立刻执行b2,但实际上await的本质是把后续代码延迟到微任务阶段执行,必须等当前主线程的所有同步代码跑完,才会轮到微任务执行。因此p1和end作为同步代码,必然比微任务里的b2先输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:07:37