async函数需配合队列、信号量等机制实现并发控制,核心是限制pending请求数量;可用手写Promise队列+计数器、p-limit库(推荐)或async-pool库,注意区分节流/防抖、服务端限频,并避免Promise.all无控并发及串行await。

async 函数本身不直接提供并发限制能力,需要配合其他机制(如 Promise 控制、队列、信号量)来实现请求的并发数控制。核心思路是:**不让所有请求同时发起,而是最多只让 N 个请求处于 pending 状态,其余排队等待**。
用 Promise 队列 + 计数器手动控制
适合轻量、明确控制逻辑的场景。维护一个当前运行中的请求数和等待队列,每次有新请求时判断是否可立即执行,否则推入队列,前序请求完成后再调度下一个。
- 定义一个最大并发数(如 max = 3)和当前运行数 running = 0
- 封装请求函数,每次调用先检查 running < max:满足则立即执行并 running++;否则推入 queue
- 每个请求 finally 中 running-- 并尝试启动队列中第一个待办任务
用 p-limit 库(推荐)
p-limit 是专为并发控制设计的轻量库,API 简洁可靠,内部基于 Promise 队列与信号量思想实现。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 安装:npm install p-limit
- 使用示例:
import pLimit from 'p-limit'; const limit = pLimit(3); // 最多 3 个并发 const requests = urls.map(url => limit(() => fetch(url).then(r => r.json())) ); const results = await Promise.all(requests);
- 它自动排队、调度、错误传播,且支持取消(v4+)、暂停等高级特性
用 async-pool(适合批量处理)
async-pool 更侧重于对一组异步任务做“池化”执行,尤其适合 map 类型的批量请求(如处理数组项)。
立即学习“Java免费学习笔记(深入)”;
- 安装:npm install async-pool
- 用法示例:
import { pool } from 'async-pool'; const results = await pool(4, urls, async url => { const res = await fetch(url); return res.json(); }); - 相比手写或 p-limit,它更强调“逐项处理 + 限流 + 收集结果”,内置错误处理选项(如跳过失败项)
注意点与常见误区
并发限制 ≠ 请求节流(throttle)或防抖(debounce);它也不解决服务端限频(rate limiting),只是客户端主动控量。
- 不要在 for 循环里直接 await 每个 fetch:这会变成串行,完全失去并发优势
- Promise.all([...]) 本身无并发限制:它会一次性触发全部 Promise,必须在外层加控
- 错误处理要统一:建议用 Promise.allSettled 替代 Promise.all,避免单个失败导致整体中断
- 超时控制建议单独加:并发限制不包含超时,需给每个请求配 AbortController 或封装 timeout

















