async/await函数执行行为异常:输出不符预期求技术解答
为什么两次调用
start()会导致异步执行顺序混乱? 问题的核心是你连续调用了两次start()函数,这两个start()是并行执行的,它们之间没有任何等待机制。每个start()内部的for循环因为await是串行执行的,但两个独立的start()调用会同时启动,导致它们的异步任务互相穿插,出现你看到的混乱输出。
详细执行流程拆解
我们一步步捋清楚代码的执行顺序:
- 第一次调用
start():- 进入
for循环(i=0),执行delayToRun(),立即打印first delay。 - 遇到
await new Promise(...),此时start()的第一个循环暂停,JavaScript引擎释放线程去执行其他任务。
- 进入
- 紧接着第二次调用
start():- 同样进入
for循环(i=0),执行delayToRun(),立即打印first delay。 - 遇到
await new Promise(...),这个start()的第一个循环也暂停,引擎继续等待任务触发。
- 同样进入
- 2秒后,两个
setTimeout同时触发,对应的Promise被resolve:- 先处理第一个
start()暂停的代码:打印second delay,返回Done,接着打印Done和分割线。然后进入i=1,执行delayToRun(),打印first delay,再次遇到await暂停。 - 接着处理第二个
start()暂停的代码:打印second delay,返回Done,打印Done和分割线。然后进入i=1,执行delayToRun(),打印first delay,遇到await暂停。
- 先处理第一个
- 又过2秒,新的两个
setTimeout触发:- 处理第一个
start()的i=1暂停代码:打印second delay、Done和分割线。 - 处理第二个
start()的i=1暂停代码:打印second delay、Done和分割线。
- 处理第一个
这就是为什么你看到输出里两个first delay先一起出现,之后是穿插的执行结果——因为两个start()完全是并行启动的,互相不等待对方完成。
实现全串行执行的修正方案
如果你希望两次start()调用也按顺序执行,需要让第二个start()等待第一个完成,修改代码如下:
const delayToRun = async() => { console.log('first delay'); let p = await new Promise((resolve, reject) => { setTimeout(() => resolve('Done'), 2000); }); console.log('second delay'); return p; }; const start = async() => { for (let i = 0; i < 2; i++) { const res = await delayToRun(); console.log(res); console.log('--------------------------------'); } }; // 让第二个start()等待第一个执行完成后再启动 start().then(() => start());
修正后的执行输出会符合你最初的预期:
first delay second delay Done -------------------------------- first delay second delay Done -------------------------------- first delay second delay Done -------------------------------- first delay second delay Done --------------------------------
内容的提问来源于stack exchange,提问作者Aisatora
相关产品推荐
相关产品推荐

