JavaScript Async/Await场景下函数立即执行问题咨询
Async/Await执行逻辑偏差说明
你对await关键字的执行时机存在两处核心误解,这是导致运行结果和预期不符的根本原因。
核心规则先明确
await仅会暂停当前async函数内部await语句之后的代码,不会延迟await后面所跟表达式本身的同步求值过程- 只有当
await接收到pending状态的Promise时,才会将async函数剩余逻辑加入微任务队列、让出当前同步执行栈;如果接收到的是普通值、或是已经落定(fulfilled/rejected)的Promise,仅会把剩余代码排进微任务队列,不会打断当前表达式的同步执行流程。
逐行拆解你提供的代码执行流
对应代码如下:
function checker() { console.log('inside checker'); return "Ok" } async function foo() { let a = await checker(); console.log("mid", a); } console.log(1); foo(); console.log('the end');
实际执行顺序完全符合JS事件循环规则:
- 全局同步代码启动,首先执行
console.log(1),输出1 - 调用
foo()进入async函数执行,碰到await checker()语句:- 第一步永远是同步计算await后面的表达式的值:立刻执行
checker()函数,触发console.log('inside checker')输出inside checker,拿到同步返回值字符串"Ok" - 由于拿到的是普通非Promise值,
await会将当前函数后续的console.log("mid", a)逻辑加入微任务队列,暂停foo函数执行,跳出函数回到全局调用栈
- 第一步永远是同步计算await后面的表达式的值:立刻执行
- 继续执行全局剩余的同步代码:运行
console.log('the end'),输出the end - 全局同步代码执行完毕、调用栈清空后,JS开始清空微任务队列:执行foo函数剩余逻辑,拿到变量a的值为
"Ok",运行console.log("mid", a),输出mid Ok
这就和你看到的输出完全一致了。
常见认知误区纠正
很多初学者会误以为写了await之后,后面跟的函数调用也会被延后,这是完全错误的:await的暂停动作发生在表达式求值完成之后,而不是之前。举个最简单的例子:
async function test() { console.log(1); await console.log(2); // console.log(2)是同步执行的 console.log(3); } test(); console.log(4);
这段代码的输出是1 2 4 3,和你遇到的问题逻辑完全一致。
如果你希望checker()的执行也发生在console.log('the end')之后,需要让await后面跟一个pending状态的Promise,把checker的执行放到微任务回调里,比如改写为:
async function foo() { let a = await Promise.resolve().then(() => checker()); console.log("mid", a); }
这时候运行输出就会变成1 the end inside checker mid Ok,符合你最初的预期。
内容的提问来源于stack exchange,提问作者Tinfinity
相关产品推荐
相关产品推荐

