如何将asyncForEach()从串行执行改为并行执行?
实现异步任务并行执行,等待全部完成后再执行后续代码
嘿,我懂你的需求——你希望循环里的异步任务同时启动并行执行,而不是挨个等待前一个完成才开始,这样总耗时就能从3秒压缩到1秒,等所有循环任务都结束后再输出Done。
原代码的问题分析
你原来的asyncForEach函数里,每次循环都用await callback(...),这会让每个异步任务都串行执行:必须等第一个任务(输出1)完成,才会开始第二个(输出2),以此类推,所以总耗时是3个1秒相加。
解决方案:用Promise.all实现并行
要让所有任务同时执行,我们可以把所有异步任务的Promise收集到一个数组里,然后用Promise.all()等待所有Promise完成,这样所有任务会同时启动,总耗时等于单个任务的最长时间(这里就是1秒)。
修改后的简化代码
const waitFor = (ms, num) => new Promise(r => setTimeout(() => { console.log(num) r() }, ms)); const doStuff = async() => { // 一次性触发所有异步任务,收集它们的Promise const taskPromises = [1, 2, 3].map(num => waitFor(1000, num)); // 等待所有Promise全部完成 await Promise.all(taskPromises); console.log('Done'); } doStuff()
保留forEach风格的并行封装(可选)
如果你还是想保留类似asyncForEach的封装方式,可以写一个并行版本的工具函数:
// 并行版本的forEach:一次性触发所有任务,等待全部完成 async function parallelForEach(array, callback) { const taskPromises = array.map((item, index) => callback(item, index, array)); await Promise.all(taskPromises); } const waitFor = (ms, num) => new Promise(r => setTimeout(() => { console.log(num) r() }, ms)); const doStuff = async() => { await parallelForEach([1, 2, 3], async(num) => { await waitFor(1000, num); }); console.log('Done'); } doStuff()
执行效果
这两段代码的输出都会在1秒后打印出1、2、3(注意:由于JS事件循环的特性,三个数字的输出顺序可能不固定,但总耗时肯定是1秒左右),然后立刻打印Done,完全符合你的期望。
内容的提问来源于stack exchange,提问作者JeX
相关产品推荐
相关产品推荐

