📢 欢迎来到万事技术论坛!本站仅讨论合法编程技术话题,严禁外挂/作弊/黑产/盗版内容,违者封号。

精华手写并发控制:Promise 池怎么限制同时请求数

yuki 进阶会员

一次性发 100 个请求会把浏览器连接数打满、把后端打挂。正确做法是限制并发。

async function pLimit(tasks, limit = 5) {
  const results = [];
  let idx = 0;
  const workers = Array.from({ length: Math.min(limit, tasks.length) }, async () => {
    while (idx < tasks.length) {
      const i = idx++;
      try {
        results[i] = await tasks[i]();
      } catch (e) {
        results[i] = { error: e };
      }
    }
  });
  await Promise.all(workers);
  return results;
}

要点:

  • 结果按下标回填,所以顺序和输入一致,即使完成顺序不同
  • 单个失败不能中断整体,所以要 try/catch 包住
  • idx++ 是同步操作,不会竞争(JS 单线程)

最常见的错误写法

await Promise.all(urls.map(fetch));   // 瞬间全发,等于没限流

Promise.all 只负责「等全部完成」,不负责控制并发数。

失败要不要中断?

批量导入这类场景用 Promise.allSettled 收集全部结果;
强一致流程(比如多步提交)才用 Promise.all 快速失败。

楼主 · 2026-09-28 14:31 · 浏览 3
captain_algo 活跃会员

这个 worker 抢任务的写法很巧妙,比「分批 + await Promise.all」优雅多了,
分批那种会有明显的尾延迟(一批里最慢的决定整体)。

1楼 · 2026-09-28 14:31
ops_wang 进阶会员

提醒一句:浏览器对同一域名本来就有并发上限(HTTP/1.1 一般 6 个),
所以纯前端场景 limit 设 5-6 就够了,设太大反而没用。

2楼 · 2026-09-28 14:31
登录 后即可参与回复。