async/await嵌套异步调用需父函数标记async及执行顺序异常疑问
问题解答
核心机制说明
你遇到的现象是async/await的既定运行规则,不属于bug:
- async函数执行后默认返回Promise对象,若要等待该异步函数执行完成再运行后续代码,必须使用
await关键字调用它 await关键字只能在被async修饰的函数内部使用,这就是你感知到「嵌套层有async调用,上级父函数都要定义为async」的原因——只有需要等待异步返回结果再执行后续逻辑的调用链路才需要逐层加async/await,不需要等待的场景可以不加,不存在强制全链路加的要求。
现有代码的问题
你的代码无法得到预期输出是两处问题导致的:
- 模拟异步的
fakeAsyncFn没有返回Promise对象,await一个非Promise值会直接同步返回,无法等待setTimeout的异步逻辑执行完成 - 所有调用async函数的位置都没有加
await,所以不会等待异步逻辑执行,会直接运行后续的console.log代码
修复方案
第一步:改造异步模拟函数返回Promise
const fakeAsyncFn = () => { return new Promise((resolve) => { setTimeout(function() { // 模拟异步调用返回结果 resolve('模拟数据') }, 100); }) };
第二步:按需给调用链路加async/await
const a = async () => { await b(); console.log('a'); }; const b = async () => { await c(); console.log('b'); }; const c = async () => { await d(); console.log('c'); }; const d = async () => { const result = await fakeAsyncFn(); // 处理返回结果的逻辑 console.log('d'); };
第三步:顶层调用
如果是在支持顶层await的环境(ES模块、Node.js v14.8及以上)可以直接调用:
await a()
如果不支持顶层await,可以用then接收执行完成回调:
a().then(() => { // 全链路执行完成后的后续逻辑 })
修改后控制台输出顺序为d、c、b、a,完全符合预期。
关于重构的说明
不需要对代码做完整重构,只有需要等待子异步函数执行完成再走后续逻辑的层级才需要加async/await修饰,其余不需要等待异步结果的层级可以保留原有逻辑。
内容的提问来源于stack exchange,提问作者bill
相关产品推荐
相关产品推荐

