async/await串行调用Promise出现并行执行的原因及解决方法
问题原因
你当前代码的核心问题是没有将setTimeout异步操作的完成和Promise的状态变更绑定:
new Promise传入的执行函数是同步运行的,调用firstFunction()时,会立刻向事件队列注册一个2秒后打印first的定时任务,随后马上执行resolve()将Promise标记为完成状态,全程没有等待定时任务触发。await只会等待Promise状态变更,此时感知到firstFunction()返回的Promise已经落定,会立刻开始执行secondFunction(),同理第二个函数也会立刻注册1秒后打印second的定时任务,随后马上resolve。- 两个定时任务先后进入事件队列,1秒的定时任务先到达触发时间,先打印
second,2秒的定时任务后触发打印first,最终呈现出你看到的并行执行效果。
修正方案
要实现真正的串行执行,只需要把resolve()调用移动到setTimeout的回调内部,等定时任务的逻辑真正执行完成后,再改变Promise状态即可,修正后代码如下:
function firstFunction () { return new Promise((resolve, reject) => { setTimeout(() => { console.log('first') resolve() // 异步操作执行完成后再将Promise标记为已完成 }, 2000) }) } function secondFunction () { return new Promise((resolve, reject) => { setTimeout(() => { console.log('second') resolve() // 异步操作执行完成后再将Promise标记为已完成 }, 1000) }) } async function main() { await firstFunction() await secondFunction() } main()
运行上述修正后的代码,会先等待2秒输出first,再等待1秒输出second,完全符合串行执行的预期。
注意:使用async/await控制异步流程时,必须确保Promise的状态变更时机和你要等待的异步操作完成时机一致,否则await无法起到正确的等待效果。
内容的提问来源于stack exchange,提问作者vman09
相关产品推荐
相关产品推荐

