
本文介绍如何将一组 promise 按固定批次(如每 2 个)分组,并确保前一批全部完成后再执行下一批,适用于 api 限流、资源节制等场景。
在实际开发中(尤其是调用后端接口时),我们常需避免并发请求过多导致服务端压力过大或触发限流。此时,简单使用 Promise.all(promises) 会一次性发起所有请求;而逐个 await 又效率过低。理想方案是:分批并发执行,批间串行等待——即每批运行 n 个 Promise,全部 resolve 后再启动下一批。
以下是一个简洁、可复用的实现:
async function runInBatches(promiseFactories, batchSize = 2) {
for (let i = 0; i < promiseFactories.length; i += batchSize) {
const batch = promiseFactories.slice(i, i + batchSize);
// 批内并发执行,批间 await 阻塞
await Promise.all(batch.map(fn => fn()));
console.log(`✅ Batch [${i}–${Math.min(i + batchSize - 1, promiseFactories.length - 1)}] completed`);
}
}
// 示例:模拟 6 个 axios 请求(注意:传入的是函数,而非已执行的 Promise)
const apiCalls = [
() => axios.post('/api', { id: 1 }),
() => axios.post('/api', { id: 2 }),
() => axios.post('/api', { id: 3 }),
() => axios.post('/api', { id: 4 }),
() => axios.post('/api', { id: 5 }),
() => axios.post('/api', { id: 6 })
];
// 每批并发 2 个请求,共 3 轮
await runInBatches(apiCalls, 2);? 关键设计说明:
Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Linux系统
- ✅ 传入的是 Promise 工厂函数(() => axios.post(...)),而非已创建的 Promise,避免请求提前发起;
- ✅ 使用 for 循环 + await Promise.all(...) 实现“批内并行、批间串行”;
- ✅ slice() 安全处理末尾不足 batchSize 的情况(自动截断,无越界风险);
- ⚠️ 若某批中任一 Promise reject,整个 Promise.all 将拒绝,需根据业务需求添加错误处理(如 Promise.allSettled 或 try/catch 包裹)。
? 进阶建议:
- 如需容错(单个失败不影响整批),可改用 Promise.allSettled;
- 如需动态控制并发数(如基于令牌桶),可结合 p-limit 等工具库;
- 在 React 或 Vue 中调用时,注意避免在渲染函数中直接 await,应封装为事件处理器或 useEffect 副作用。
该模式兼顾效率与可控性,是前端批量请求调度的经典实践。









