如何按批次串行执行Promise.all,避免批量请求引发系统崩溃?
解决串行执行Promise批次的问题
嘿Ollie,我完全懂你的困扰——直接遍历拆分后的批次执行Promise.all的话,所有请求批次会几乎同时发起,根本没做到等上一批完成再跑下一批,这不就跟没拆分一样嘛!别担心,这就给你几个简单好用的解决方案。
方法一:用async/await + for...of(最直观易维护)
这是最容易理解的写法,利用for...of循环会等待每一次迭代里的await完成的特性,完美实现串行批次执行:
async function processInfluencerAccounts() { // 生成所有请求的Promise const influencerAccounts = wrapper.map(p => addInfluencerAccounts(p)); // 拆分成每50个一组 const chunkedPromises = _.chunk(influencerAccounts, 50); const allResults = []; // 串行处理每一批 for (const chunk of chunkedPromises) { console.log(`正在执行第${Math.floor(allResults.length / 50) + 1}批请求...`); // 等待当前批次所有请求完成 const chunkResults = await Promise.all(chunk); // 把当前批次结果合并到总结果里 allResults.push(...chunkResults); } return allResults; } // 调用函数并处理结果/错误 processInfluencerAccounts() .then(finalResults => { console.log(`所有${finalResults.length}个请求都完成啦!`, finalResults); // 这里可以继续处理最终结果 }) .catch(error => { console.error("某一批次请求出错了:", error); // 错误处理逻辑,比如记录日志、重试等 });
方法二:用Array.reduce(函数式风格)
如果你偏爱函数式写法,可以用reduce来累积Promise,实现串行执行:
// 生成Promise并拆分批次 const influencerAccounts = wrapper.map(p => addInfluencerAccounts(p)); const chunkedPromises = _.chunk(influencerAccounts, 50); // 用reduce串行执行每一批 const allResultsPromise = chunkedPromises.reduce(async (accumulatorPromise, currentChunk) => { // 先等待上一批的结果 const accumulator = await accumulatorPromise; // 执行当前批次 const currentResults = await Promise.all(currentChunk); // 合并结果并返回新的Promise return [...accumulator, ...currentResults]; }, Promise.resolve([])); // 初始值是一个已resolve的空数组Promise // 处理最终结果 allResultsPromise .then(finalResults => { console.log("所有请求完成:", finalResults); }) .catch(error => { console.error("请求出错:", error); });
额外优化:容错处理(可选)
如果担心某一个请求失败导致整个批次中断,可以把Promise.all换成Promise.allSettled,这样即使部分请求失败,也能继续执行下一批,还能收集所有请求的状态:
// 在for...of循环里替换成: const chunkResults = await Promise.allSettled(chunk); // 过滤出成功的结果 const successfulResults = chunkResults .filter(result => result.status === 'fulfilled') .map(result => result.value); allResults.push(...successfulResults); // 也可以收集失败的请求以便后续处理 const failedRequests = chunkResults .filter(result => result.status === 'rejected') .map(result => result.reason); if (failedRequests.length > 0) { console.warn(`当前批次有${failedRequests.length}个请求失败:`, failedRequests); }
这样就算某一批里有请求失败,整个串行流程不会被打断,还能记录失败的请求信息。
内容的提问来源于stack exchange,提问作者Ollie
相关产品推荐
相关产品推荐

