JavaScript中await未按预期等待后续代码执行的原因排查
JavaScript异步执行顺序问题排查与解决
我正在学习JavaScript异步操作,编写了以下代码:
async function cout_after10(num) { setTimeout(() => { console.log(num) }, 10) }; async function cout_after0(num) { setTimeout(() => { console.log(num) }, 0) }; // 主函数 (async function () { async function test() { await console.log(1) console.log(3) setTimeout(() => console.log(7), 5) console.log(4) } test() console.log(2) await cout_after10(8) await cout_after0(6) console.log(5) })();
输出差异问题
我预期的输出是:
1, 2, 3, 4, 5, 7, 8, 6
但实际输出是数字升序,最后三位和预期完全不符。
我对执行顺序的理解
- 同步执行
test(),进入test作用域,打印1,将后续代码放入微任务队列。 - 打印2。
- 执行
cout_after10(8),因为是异步函数,将其放入宏任务队列;await会阻塞后续代码,直到该函数完成,同时把后续代码放入微任务队列。 - 同步代码执行完毕,从微任务队列取出任务执行:打印3,将
setTimeout(() => console.log(7), 5)放入宏任务队列,然后打印4。 - 执行微任务队列中
await cout_after10(8)后的代码:将cout_after0(6)放入宏任务队列,把console.log(5)放入微任务队列。 - 微任务队列仅剩
console.log(5),执行并打印5。
核心困惑
后续宏任务的执行顺序完全超出预期:
7. 我认为宏任务队列会按插入顺序执行以下任务:
setTimeout(() => console.log(7), 5); cout_after10(8); cout_after0(6);
理论上应该打印7、8、6,但实际是按延迟时间从短到长的顺序打印6、7、8。
另外,我原本以为await会保证顺序执行:
await cout_after10(8); await cout_after0(6);
应该先打印8再打印6,但实际并非如此,await没有起到预期的阻塞作用。
问题根源与修正方案
问题出在异步函数没有返回Promise。async函数如果没有显式返回Promise,会默认返回一个已resolved的Promise,导致await不会等待内部的setTimeout完成。修改代码让函数返回Promise后,即可按预期顺序执行:
async function cout_after10(num) { return new Promise((resolve) => { setTimeout(() => { console.log(num) resolve(0) }, 10) }) }; async function cout_after0(num) { return new Promise((resolve) => { setTimeout(() => { console.log(num) resolve(0) }, 0) }) }; // 主函数 (async function () { async function test() { await console.log(1) console.log(3) setTimeout(() => console.log(7), 5) console.log(4) } test() console.log(2) await cout_after10(8) await cout_after0(6) console.log(5) })();
内容的提问来源于stack exchange,提问作者香辛料
相关产品推荐
相关产品推荐

