如何在await循环中批量顺序执行Promise.all并增量收集返回数据
问题分析
你原有代码无法实现需求的核心原因有两点:
- 传入
Promise.all的是未执行的异步函数数组,Promise.all只会处理Promise实例,不会主动执行函数,不会触发实际的异步调用 - reduce累计值传递逻辑错误,同时依赖外部变量
finalData存储结果,存在副作用,也不符合累计合并数据的要求
修正代码
基于reduce写法的调整版(尽量保留原有代码风格)
private asyncForEach(PromiseGroups: Array<Array<() => Promise<{data: Array<any>, status: number}>>): Promise<Array<any>> { return PromiseGroups.reduce(async (acc, currentGroup) => { // 等待上一批次执行完成,拿到累计的数据集 const accumulatedData = await acc; // 主动执行当前批次所有异步函数,得到Promise数组后等待全部完成 const currentBatchRes = await Promise.all(currentGroup.map(func => func())); // 合并当前批次的data字段到累计结果中 return [...accumulatedData, ...currentBatchRes.flatMap(res => res.data)]; }, Promise.resolve([])) } // 调用示例 // const finalData = await asyncForEach(callSet);
更易理解的for循环版本
如果觉得reduce的异步累计逻辑晦涩,可以换成普通for循环实现,逻辑更直观:
private async executeByBatch(PromiseGroups: Array<Array<() => Promise<{data: Array<any>, status: number}>>): Promise<Array<any>> { const finalData = []; // 按顺序遍历每个批次 for (const group of PromiseGroups) { // 并行执行当前批次所有异步函数,等待全部完成 const batchResults = await Promise.all(group.map(func => func())); // 合并当前批次所有data数据到最终结果 finalData.push(...batchResults.flatMap(item => item.data)); } return finalData; }
实现说明
- 严格按批次顺序执行:只有上一批次所有函数执行完成、数据合并完毕后,才会触发下一批次的调用
- 每个批次内的函数并行执行,符合需求逻辑
- 没有外部变量依赖,直接返回合并后的最终数据集,无副作用
- 用
flatMap直接展开每个返回结果的data数组,替代手动concat操作,代码更简洁
内容的提问来源于stack exchange,提问作者User985614
相关产品推荐
相关产品推荐

