You need to enable JavaScript to run this app. 使用Promise.allSettled发起大量请求时如何避免阻塞其他新请求
优惠活动
大模型
产品
解决方案
定价
更多

使用Promise.allSettled发起大量请求时如何避免阻塞其他新请求

解决方案

问题根因

你遇到的阻塞本质是浏览器对同域名的最大并发请求数限制(Chrome/Edge等主流浏览器默认是6个),你一次性发起100个请求时,剩下94个请求会进入浏览器的请求队列排队,此时用户触发的新请求(比如retriveUserDetail)也会排在队列末尾,等轮到它的时候早就超过10s的前端超时时间,自然会被取消。
另外你的代码有个常见误区:循环中直接调用createParticipant时请求就已经发出了,Promise.allSettled只是用来等待所有请求的结果,不是控制请求发起的时机。

可行优化方案

1. 批量请求并发数控制(最推荐)

不要一次性发起全部100个请求,限制批量任务的同时请求数(建议设为34,预留23个空位给用户主动触发的高优先级请求),就能从根本上避免队列阻塞。
以下是并发控制的实现代码:

// 并发控制工具函数,limit是最大同时请求数
const concurrentRun = async (tasks, limit = 3) => {
  const results = []
  const executing = []
  for (const task of tasks) {
    // 包装任务,执行完后从执行队列移除
    const p = Promise.resolve().then(task)
    results.push(p)
    executing.push(p)
    const clean = () => executing.splice(executing.indexOf(p), 1)
    p.then(clean, clean)
    // 执行队列满了就等任意一个请求完成再进下一个
    if (executing.length >= limit) {
      // 每批完成后留50ms空隙处理其他用户请求
      await Promise.race(executing)
      await new Promise(resolve => setTimeout(resolve, 50))
    }
  }
  return Promise.allSettled(results)
}

// 改造你的批量创建逻辑
// 注意:这里要先把请求包装成函数,不要直接调用,否则还是会一次性发请求
const taskList = []
for (let i = 0; i < totalNumber; i++) {
  const participant = participantList[i]
  const participantNewDetail = {
    firstName: participant.firstName,
    lastName: participant.lastName,
    email: participant.email,
  }
  // 包装成函数,执行时才发起请求
  taskList.push(() => createParticipant(participantNewDetail)
    .then((createParticipantResult) => {
      processedTask++
      processMessage = `Processing adding participant`
      dispatch({ type: ACTIVATE_PROCESS_PROCESSING, payload: { processedTask, processMessage } })
    })
    .catch((error) => {
      processedTask++
      processMessage = `Processing adding participant`
      dispatch({ type: ACTIVATE_PROCESS_PROCESSING, payload: { processedTask, processMessage } })
      throw new Error(
        JSON.stringify({
          status: "failed",
          value: error.data.message ? error.data.message : error,
        })
      )
    })
  )
}

// 限制最多3个并发执行批量请求
const addParticipantResults = await concurrentRun(taskList, 3)

2. 拆分请求优先级

  • 拆分两个axios实例:交互类请求(用户主动点击触发的查询、操作)用一个实例,保持10s超时;批量后台任务用另一个实例,超时设为20s和后端匹配,避免批量请求提前失败。
  • 如果有高优先级请求发起时,可以主动暂停批量任务的执行,等高优先级请求完成后再恢复批量任务,体验会更流畅。

3. 后端接口优化(可选)

如果业务允许,后端可以新增一个批量创建参与者的接口,前端一次性传100条数据,只需要发起1次POST请求,完全不存在并发阻塞问题,性能也会高很多。

关于拆分小批量请求的疑问

完全可以拆成多个小数组分批发送,上述并发控制方案本质就是自动分批的逻辑,你也可以手动按10个一组拆分,每执行完一组就留100ms的空闲窗口处理其他请求,效果是一样的。

内容的提问来源于stack exchange,提问作者Moon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 18:15:08