Promise本身不提供并发控制,但可通过封装结合信号量与队列实现动态限流:维护activeCount、maxConcurrency和FIFO队列,用schedule调度、done释放,支持运行时setLimit调整上限。

Promise 本身不提供并发控制能力,但可以通过封装 Promise 创建逻辑,结合队列和计数器机制,实现动态限流——即在运行时灵活调整最大并发请求数(如从 3 改为 5),而无需重启或重建请求流程。
用“信号量 + 队列”管理并发数
核心思路是维护一个当前活跃请求数(activeCount)和一个待执行任务队列。每次发起新请求前,先检查是否已达上限;未达上限则立即执行,否则入队等待;任一请求完成(无论成功或失败)后,尝试从队列中取出下一个任务执行。
- 定义一个可修改的
maxConcurrency变量,作为当前限流阈值 - 用
activeCount实时跟踪正在 pending 的 Promise 数量 - 用数组模拟先进先出队列,存放待执行的请求函数(返回 Promise 的函数)
- 封装一个
schedule方法,统一调度:检查、执行或入队
封装成可动态调优的限流类
把逻辑封装成类,暴露 setLimit(n) 方法,允许运行时调整并发上限。注意:新设置只影响后续调度,已在执行的请求不受影响,已排队任务也不会被丢弃或重排。
- 构造时初始化
maxConcurrency = 1、activeCount = 0、queue = [] -
add(promiseFn)接收一个无参函数,该函数调用后返回 Promise(如() => fetch(url)) -
setLimit(n)直接赋值this.maxConcurrency = Math.max(1, n | 0),然后触发一次drain() -
drain()是关键:只要activeCount < maxConcurrency且队列非空,就取出一个任务执行,并增加activeCount
每个 Promise 完成后自动释放并续发
每个请求 Promise 的 then 和 catch 分支都必须调用统一的 done() 回调,用于减少计数并尝试调度下一个任务。不能只在 then 中处理,否则失败请求会卡住并发槽位。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 执行
promiseFn()后,在其返回的 Promise 上链式调用.finally(() => done()) -
done()内部做两件事:减activeCount,再调用drain() - 这样即使某个请求 404 或超时,也不会阻塞后续任务调度
使用示例:启动 10 个请求,初始限流 2,中途改为 4
你可以创建实例后,先批量添加请求,再随时调用 setLimit() 调整。实际并发数会平滑过渡,不会中断已有请求。
const limiter = new ConcurrencyLimiter(2);
// 批量添加 10 个请求(不立即执行)
Array.from({ length: 10 }, (_, i) =>
limiter.add(() => fetch(`/api/item/${i}`).then(r => r.json()))
);
// 2 秒后提升并发到 4
setTimeout(() => limiter.setLimit(4), 2000);
这种设计轻量、无第三方依赖,适用于浏览器和 Node.js,也便于与 async/await 配合使用。关键是把“执行权”收归调度器,而不是放任 Promise 自由触发。

















