如何在async异步函数内部调用异步代码使外层函数先执行完成
现象原因
async/await 本质是 Promise 的语法糖,运行规则完全遵循 JS 事件循环机制:
- 调用 async 函数时,会同步执行函数内的代码直到碰到第一个
await关键字 - 碰到
await后,会将await之后的所有代码封装为微任务,挂入微任务队列等待执行,同时 async 函数直接返回一个 pending 状态的 Promise - 外层如果用
await接收这个 async 函数返回的 Promise,外层await之后的代码也会被封装为依赖该 Promise 兑现后才执行的微任务,所以会等内层 async 函数的所有逻辑执行完毕、Promise 被 resolve 后才会运行。
这就是第二个示例中 after asyncInner 早于 after asyncOuter 输出的原因:外层 asyncOuter 的后续逻辑被绑定到了 asyncInner 返回的 Promise 上,必须等内层执行完才能触发。
实现方案
如果要让 asyncOuter 全部执行完毕后再运行 asyncInner 的后续逻辑,只需要调整 await 的时机:不要在 asyncInner 调用时就立刻 await,先执行完 asyncOuter 自身的所有逻辑后,再等待 asyncInner 的 Promise 兑现即可。
示例代码1(保留asyncInner提前调用的同步逻辑)
如果允许 before asyncInner 提前执行,只延后 await 后的后续逻辑:
async function asyncInner() { console.log('before asyncInner'); await Promise.resolve() console.log('after asyncInner'); } async function asyncOuter() { console.log('before asyncOuter'); // 先调用asyncInner拿到Promise,但不立刻await const innerPromise = asyncInner(); // 先执行完asyncOuter自身所有逻辑 console.log('after asyncOuter'); // 自身逻辑执行完毕后再等待asyncInner的后续执行 await innerPromise; } console.log('start'); asyncOuter() console.log('end');
输出结果:
start before asyncOuter before asyncInner after asyncOuter end after asyncInner
示例代码2(完全延后asyncInner的所有执行)
如果需要连 before asyncInner 也在 asyncOuter 执行完后再运行,直接把 asyncInner 的调用时机延后即可:
async function asyncInner() { console.log('before asyncInner'); await Promise.resolve() console.log('after asyncInner'); } async function asyncOuter() { console.log('before asyncOuter'); // 先执行完asyncOuter自身所有逻辑 console.log('after asyncOuter'); // 自身逻辑执行完毕后再调用并等待asyncInner await asyncInner(); } console.log('start'); asyncOuter() console.log('end');
输出结果:
start before asyncOuter after asyncOuter before asyncInner end after asyncInner
两种方案都没有用到回调,完全保持了 async 语法的线性编写风格。
内容的提问来源于stack exchange,提问作者Joshua Frank
相关产品推荐
相关产品推荐

