前端批量请求的并发控制与工程化实践

在上一篇文章中,我们已经完成了数据准备工作。本篇将重点介绍一个在真实业务中几乎绕不开的问题

当需要对一组数据逐个请求接口时,如何优雅、安全地进行批量请求?

如果处理不当,轻则页面卡顿,重则接口被限流甚至封禁。


一、为什么不能直接 Promise.all

最常见的写法是这样:

ini 复制代码
Promise.all(
  list.map(item => request(item))
);

这个写法的问题在于:

  • 并发数量 不可控

  • 列表一长就会:

    • 打满浏览器并发
    • 压垮后端服务
  • 一旦某个请求失败,整体直接 reject

在区县、设备、用户、文件等数量不确定的场景下,这种方式风险极高。


二、我们真正需要的是什么?

一个成熟的「批量请求」方案,至少应该满足:

  1. 限制并发数量
  2. 支持批次间隔(节流)
  3. 单个失败不影响整体流程
  4. 能够感知整体完成状态
  5. 结果和错误可以分开统计

三、核心设计思路

1️⃣ 把"请求"和"执行"解耦

  • 批量工具只负责 调度
  • 具体请求由调用方传入
javascript 复制代码
(task) => Promise

2️⃣ 固定并发数,分批执行

  • 每一批最多 N 个任务
  • 当前批次完成后,延迟一段时间再执行下一批

3️⃣ 所有任务最终返回一个统一结果

ini 复制代码
{
  results: [],
  errors: []
}

四、批量请求使用方式(示例)

下面是一个典型的使用方式:

javascript 复制代码
this.batchRequestWithLimit(
  taskList,
  (task) => {
    return apiRequest(task);
  },
  (task, data) => {
    console.log(`任务 ${task} 成功`, data);
  },
  5,   // 最大并发数
  200, // 批次间隔(ms)
)
  .then(({ results, errors }) => {
    console.log(
      `批量请求完成:成功 ${results.length} 个,失败 ${errors.length} 个`
    );
  })
  .catch(err => {
    console.error("批量请求异常:", err);
  });

从使用者视角看,这个方法具备:

  • 调用简单
  • 参数语义清晰
  • 结果可控

五、执行流程拆解(非常关键)

整个批量请求的生命周期可以拆成 5 步:

Step 1:任务队列初始化

ini 复制代码
const queue = [...taskList];

Step 2:取出当前批次

ini 复制代码
const batch = queue.splice(0, limit);

Step 3:并发执行当前批次

ini 复制代码
await Promise.allSettled(
  batch.map(task => executor(task))
);

Step 4:等待节流时间

scss 复制代码
await sleep(interval);

Step 5:继续下一批,直到队列清空


六、为什么 Promise.allSettled 是关键

相比 Promise.all

方法 任一失败 结果可控
Promise.all ❌ 整体失败
Promise.allSettled ✅ 单独失败

批量请求场景中

失败是常态,而不是异常

我们要做的是:

  • 接受失败
  • 记录失败
  • 不中断流程

七、这种模式适合哪些场景?

这种批量请求模型,适用于:

  • 区县 / 城市 / 设备 / 用户 批量拉取
  • 文件批量上传 / 下载
  • 批量校验、扫描、统计
  • 任何「数量不确定 + 接口有压力」的业务场景

八、总结一句话

批量请求不是"多发请求",而是"有节制地并发执行任务"。

通过:

  • 限制并发
  • 分批执行
  • 错误隔离
  • 统一收敛结果

你可以把一个"危险操作",变成一个可控、可扩展、可维护的工程能力

相关推荐
weipt2 小时前
关于vue项目中cesium的地图显示问题
前端·javascript·vue.js·cesium·卫星影像·地形
懒大王、2 小时前
Vue3 + OpenSeadragon 实现 MRXS 病理切片图像预览
前端·javascript·vue.js·openseadragon·mrxs
诗意地回家3 小时前
淘宝小游戏反编译
开发语言·前端·javascript
徐同保3 小时前
react两个组件中间加一个可以拖动跳转左右大小的功能
前端·javascript·react.js
bjzhang753 小时前
使用 HTML + JavaScript 实现在线知识挑战
前端·javascript·html
alamhubb4 小时前
反感pnpm的全链路污染?可以了解下这个对原项目零侵入,零修改完全兼容npm的monorepo工具
前端·javascript·node.js
2501_948194984 小时前
RN for OpenHarmony AnimeHub项目实战:正在热播页面开发
javascript·react native·react.js
2501_944521004 小时前
rn_for_openharmony商城项目app实战-语言设置实现
javascript·数据库·react native·react.js·harmonyos
AdleyTales4 小时前
vscode识别不了@提示找不到路径解决
前端·javascript·vscode