为何外部触发多调用时async/await无法保证执行顺序?
为什么异步函数直接连续调用会出现执行交错?
先看你用到的异步函数代码:
async function doWork(id) { console.log("Start", id); await new Promise(res => setTimeout(res, 1000)); console.log("End", id); }
带await顺序调用的执行逻辑
当你用await依次调用时:
await doWork(1); await doWork(2);
- 执行
await doWork(1)时,立刻进入函数打印Start 1,遇到await后,函数暂停执行,主线程会等待这个await后的Promise完成。 - 1秒后定时器触发,Promise resolve,
doWork(1)恢复执行打印End 1,整个函数执行完毕。 - 这时才会启动
await doWork(2),重复上述流程,所以输出是严格的顺序:
Start 1 End 1 Start 2 End 2
无await连续调用的执行逻辑
当你直接连续调用时:
doWork(1); doWork(2); doWork(3);
- 调用
doWork(1)后,立刻执行到await前的代码,打印Start 1,遇到await函数暂停,但主线程不会等这个Promise完成,直接跳到下一行调用doWork(2)。 - 同理,
doWork(2)打印Start 2后暂停,主线程继续调用doWork(3)打印Start 3后暂停。 - 三个定时器几乎是同时被设置的,1秒后它们的回调会依次进入事件队列。
- 主线程空闲后,按顺序处理这些回调,依次让三个函数恢复执行,打印
End 1、End 2、End 3。
所以最终输出就是交错的:
Start 1 Start 2 Start 3 End 1 End 2 End 3
核心原因
async函数里的await会暂停当前函数执行,把后续代码放到微任务队列,等Promise resolve后再执行。- 不用
await调用async函数时,函数返回的Promise不会被等待,主线程会连续执行所有调用的同步部分(await之前的代码),而它们的异步部分会在各自的定时器到期后依次完成。 - 本质就是:带
await是串行执行,必须等前一个函数完全结束才启动下一个;不带await是并行启动多个异步任务,同步部分先批量执行,异步部分在同一时间点后依次收尾。
内容的提问来源于stack exchange,提问作者user10430344
相关产品推荐
相关产品推荐

