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()的完整执行步骤:
- 调用
b()后,先同步执行console.log("b1"),输出b1。 - 执行
await a()时,先同步调用a(),所以a内部的console.log("a")立即执行,输出a。 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
相关产品推荐
相关产品推荐

