在循环中使用await是否属于良好的编程实践?
在for循环中使用await的合理性与实践场景
首先纠正你对MDN那段话的理解:每次迭代遇到await时,只有当前迭代中依赖该await结果的后续代码(比如示例里的console.log(zero))会暂停并进入微任务队列,而循环的下一次迭代以及循环外的console.log(r)(//2)并不会在每次迭代时都被推入队列。只有当当前await的Promise完成后,才会继续执行当前迭代的剩余代码,然后进入下一次循环;等整个循环的所有迭代都完成后,才会执行循环外的console.log(r)。
这种做法是否属于良好实践?
答案是分场景而定,它本身是JavaScript规范允许的写法,MDN也明确了await的执行机制,在特定需求下是合理且推荐的:
适用场景:
- 任务存在依赖关系:比如下一个异步操作需要用上一个操作的返回结果,必须串行执行才能保证逻辑正确。
- 受资源/速率限制:比如调用第三方API有请求频率限制,串行发送请求可以避免触发限流机制;或者操作占用大量资源,并行执行会导致性能问题。
- 需要严格保证执行顺序:业务逻辑要求任务按顺序完成,比如按顺序处理用户的操作日志、依次写入文件等。
不适用场景:
如果异步任务之间没有依赖关系,这种串行写法会浪费性能——因为每个任务都要等前一个完成才开始,总耗时是所有任务耗时的总和。此时应该用Promise.all()并行执行,总耗时等于耗时最长的那个任务,比如:
let zeros = new Array(10).fill(0); (async () => { // 并行执行所有异步任务 const results = await Promise.all(zeros.map(() => new Promise((r) => setTimeout(r.bind(null, 1), 10)) )); zeros.forEach(zero => console.log(zero)); console.log(results[results.length - 1]); // 取最后一个结果 })();
对你提供的代码的说明
你的示例代码会每隔10ms输出一个0,一共输出10次,最后输出1。因为每次循环都会等待10ms的定时器完成后,才会执行console.log(zero)并进入下一次循环,属于典型的串行异步执行场景。
内容的提问来源于stack exchange,提问作者stackhatter
相关产品推荐
相关产品推荐

