关于async调用与setTimeout执行顺序的技术疑问
为什么异步代码输出顺序是'a','b','c'而非预期的'c','a','b'?
先看你提供的代码:
async function apiCall() { return new Promise((resolve) => { setTimeout(() => { resolve('b'); }, 50); }); } async function logger() { setTimeout(() => console.log('a'), 10); console.log(await apiCall()); console.log('c'); } logger();
执行流程拆解
- 调用
logger()后,首先执行第一个setTimeout:它会把打印'a'的回调加入宏任务队列,标记10ms后可执行。 - 接下来执行
console.log(await apiCall()):这里的await会直接暂停logger函数的执行,必须等apiCall返回的Promise被resolve后,才会继续往下执行后续代码。apiCall返回的Promise内部还有一个setTimeout,它会把resolve('b')的回调加入宏任务队列,标记50ms后可执行。
- 此时
logger处于暂停状态,JS引擎开始处理宏任务队列:10ms到点后,打印'a'的回调执行,输出'a'。 - 再等40ms(累计50ms),
apiCall里的resolve回调触发,Promise状态变为resolved,logger函数恢复执行,打印出'b'。 - 最后执行
console.log('c'),输出'c'。
你的误解点
你以为await在console.log内部就不会阻塞后续代码,但实际上**await的作用是暂停整个当前async函数的执行流程**,不管它嵌套在哪个语句里。只要async函数遇到await,就会停在当前行,等待关联的Promise处理完成后,才会继续执行函数内await之后的所有代码。所以console.log('c')必须等前面的await完成后才会执行,不可能先于'b'输出。
内容的提问来源于stack exchange,提问作者Cjmaret
相关产品推荐
相关产品推荐

