JS代码执行顺序疑问:实际输出为何与预期不符?
关于JavaScript异步执行顺序的疑问
代码示例
async function async1() { console.log("a"); await async2(); console.log("b"); } async function async2() { console.log("c"); await async3(); console.log("zzzzz"); } const async3 = async () => { console.log("qqqq"); }; console.log("d"); async1(); setTimeout(() => { console.log("e"); }, 0); new Promise((resolve, reject) => { console.log("f"); resolve(); }).then(() => { console.log("g"); });
预期与实际输出
- 预期输出顺序:
d, a, c, qqqq, f, zzzzz, b, g, e - 实际输出顺序:
d a c qqqq f zzzzz g b e
疑问点
我认为首次同步执行完成后,微任务队列应为console.log("zzzzz"); console.log("b"); console.log("g");,执行顺序应该是zzzzz、b、g,但实际结果并非如此,想请教我的理解哪里有误?
问题分析
你对微任务队列的顺序理解存在偏差,核心是搞清楚**await后续代码的入队时机**以及微任务队列的执行逻辑:
先理清楚同步执行阶段的完整流程:
- 首先执行
console.log("d"),输出d - 调用
async1():- 执行
console.log("a"),输出a - 调用
async2():- 执行
console.log("c"),输出c - 调用
async3():执行console.log("qqqq"),输出qqqq。因为async3是async函数,执行后返回一个已resolved的Promise,所以await async3()会把它后面的console.log("zzzzz")加入微任务队列,此时async2暂停执行,回到async1
- 执行
async1执行到await async2()时,因为async2还没执行完(它的后续代码还在微任务队列里),所以async1的await后续代码console.log("b")暂时不会入队,要等async2完全执行完毕、返回resolved的Promise后,才会被加入微任务队列
- 执行
- 接下来执行
setTimeout,把console.log("e")加入宏任务队列 - 执行
new Promise的 executor 函数:console.log("f")输出f,调用resolve()后,把then回调里的console.log("g")加入微任务队列
- 首先执行
同步阶段结束时,微任务队列的内容是:
- 第一个:
console.log("zzzzz")(来自async2的await后续) - 第二个:
console.log("g")(来自Promise的then)
- 第一个:
开始执行微任务队列:
- 先执行
console.log("zzzzz"),输出zzzzz。此时async2完全执行完毕,返回resolved的Promise,这时候async1中await async2()的后续代码console.log("b")才被加入微任务队列 - 接着执行
console.log("g"),输出g - 微任务队列现在新增了
console.log("b"),继续执行它,输出b
- 先执行
微任务队列清空后,执行宏任务队列里的
setTimeout回调,输出e
所以实际输出顺序和浏览器一致。你的错误在于误以为async1的await后续代码会在同步阶段结束就进入微任务队列,但实际上它要等async2整个函数执行完成后才会入队,所以排在了g的后面。
内容的提问来源于stack exchange,提问作者qizhi hu
相关产品推荐
相关产品推荐

