为什么`after resolve`的执行顺序早于`after wait`?
JavaScript微任务队列执行顺序的误区解析
问题背景
我编写了一段JavaScript代码,运行后实际输出中after resolve早于after wait执行,但我原本以为after wait会更早被推入微任务队列并先执行,想知道这个认知存在什么误区。
原始代码
console.log('test') async function async1() { console.log('before wait'); await wait(); console.log('after wait'); } async function wait() { try { return await new Promise((res, rej) => { console.log('wait'); rej('reject'); }); } catch (reason) { console.log(reason); } } async function test() { async1(); console.log('before resolve'); await Promise.resolve(); console.log('after resolve'); } test(); console.log('test end');
实际输出
[LOG]: "test" [LOG]: "before wait" [LOG]: "wait" [LOG]: "before resolve" [LOG]: "test end" [LOG]: "reject" [LOG]: "after resolve" [LOG]: "after wait"
改写后的代码(替换async/await为then)
console.log('test') function async1() { console.log('before wait'); return wait().then(() => { console.log('after wait'); }) } function wait() { return new Promise((res, rej) => { console.log('wait'); rej('reject'); }).catch((reason) => { console.log(reason); }) } function test() { async1(); console.log('before resolve'); Promise.resolve().then(() => { console.log('after resolve'); }) } test(); console.log('test end');
核心误区解析
你的错误认知在于误以为async1中await wait()的后续代码会比test中await Promise.resolve()的后续代码更早进入微任务队列,但实际执行流程中两者的入队时间有先后差,具体拆解如下:
1. 同步代码执行阶段
- 先执行全局同步代码:打印
test,调用test()函数 - 进入
test():- 调用
async1(),打印before wait后调用wait() - 进入
wait():创建Promise并执行executor,打印wait后直接reject,此时这个Promise变为rejected状态;await这个rejected Promise会暂停wait()的执行,将catch块的逻辑(打印reason)放入微任务队列,同时wait()返回一个pending状态的Promise给async1的await - 回到
test(),继续执行同步代码:打印before resolve,然后await Promise.resolve()会将console.log('after resolve')放入微任务队列,test()返回pending Promise
- 调用
- 最后执行全局同步代码:打印
test end
此时微任务队列的顺序是:
- 第一顺位:
wait()中处理reject的catch块(打印reject) - 第二顺位:
test()中await Promise.resolve()后的console.log('after resolve')
2. 微任务处理阶段
- 先执行第一顺位微任务:打印
reject,此时wait()的catch执行完毕,wait()返回的Promise变为resolved状态 - 只有当
wait()的Promise变为resolved后,async1中的await wait()才会完成,将console.log('after wait')加入微任务队列 - 接着执行第二顺位微任务:打印
after resolve - 最后执行新加入的微任务:打印
after wait
简单来说,wait()返回的Promise并非立即resolved,它需要等内部的catch微任务执行完毕才会切换状态,这直接导致async1中await的后续代码入队时间晚于test中await Promise.resolve()的后续代码,最终出现after resolve先执行的结果。
内容的提问来源于stack exchange,提问作者YJ Cai
相关产品推荐
相关产品推荐

