Async/Await与for循环结合未达预期,新手求助原因
问题解析:为什么你的Promise定时器会同时触发?
嘿,我来帮你理清楚这个问题~你遇到的情况其实是因为同步循环和异步操作的执行顺序差异导致的,咱们一步步拆解代码的执行流程就明白了:
原代码的执行逻辑
先把你的代码再贴一遍方便分析:
for(let i = 0; i < 3 ; i++){ func(callback,i); } async function func(callback,i){ await callback(i); } function callback(i){ return new Promise((res,rej) =>{ setTimeout(()=>{ console.log('i = ',i) res(); }, 2000); }) }
- 同步for循环优先执行:for循环是同步代码,它会在瞬间完成三次
func(callback,i)的调用,完全不会等待func里的await完成。 - 三个定时器同时启动:每次调用
func时,callback都会立刻返回一个Promise,并且里面的setTimeout会马上开始计时(都是2秒后触发)。这意味着三个定时器几乎是在同一时间开始倒计时的。 - 2秒后批量执行:当2秒时间到,三个定时器的回调函数会被依次加入事件队列,然后连续执行,所以你会看到一次性打印出三个i值。
简单来说,你的代码相当于同时按下了三个2秒后的闹钟,它们自然会同时响起来~
如何修改成“每隔2秒打印一次”
要实现每隔2秒打印的效果,核心是让下一次循环等待上一次的异步操作完成。你可以把循环放在一个async函数里,并且在每次调用func时加上await:
async function run() { for(let i = 0; i < 3 ; i++){ await func(callback,i); // 等待上一次的Promise完成,再进入下一次循环 } } // 启动执行 run(); async function func(callback,i){ await callback(i); } function callback(i){ return new Promise((res,rej) =>{ setTimeout(()=>{ console.log('i = ',i) res(); }, 2000); }) }
这样修改后,第一次循环会等待func(callback,0)的Promise完成(也就是2秒后打印i=0并resolve),才会进入i=1的循环,以此类推,就能实现每隔2秒打印一次的效果了。
内容的提问来源于stack exchange,提问作者Venkatesh
相关产品推荐
相关产品推荐

