Promise池通过维护运行中任务队列实现并发控制,核心是限制同时执行的请求数量并排队调度;手动实现需跟踪索引与运行数,或用ConcurrencyController类封装信号量逻辑,生产环境推荐p-limit库。

用 Promise 控制并发请求数量,核心思路是维护一个“运行中任务队列”,确保任意时刻最多只有指定数量的请求在进行,其余请求排队等待。最常用、简洁且可靠的方式是使用 Promise 池(Promise Pool) 模式,不依赖第三方库也能轻松实现。
手动实现一个轻量 Promise 池
下面是一个通用、可复用的 promisePool 函数:
function promisePool(tasks, limit = 3) {
const results = [];
let currentIndex = 0;
let running = 0;
return new Promise((resolve) => {
function runNext() {
if (currentIndex >= tasks.length && running === 0) {
resolve(results);
return;
}
while (running < limit && currentIndex < tasks.length) {
const task = tasks[currentIndex++];
running++;
task()
.then(result => {
results.push({ status: 'fulfilled', value: result });
})
.catch(error => {
results.push({ status: 'rejected', reason: error });
})
.finally(() => {
running--;
runNext();
});
}
}
runNext();
});
}
用法示例(同时最多发 2 个请求):
const urls = ['/api/1', '/api/2', '/api/3', '/api/4']; const requests = urls.map(url => () => fetch(url).then(r => r.json())); promisePool(requests, 2) .then(results => console.log(results)); // 每个结果含 status 和 value/reason
用 async/await + 串行调度器更易读
如果希望逻辑更清晰、便于调试,可以用一个“信号量”(Semaphore)思想的简易调度器:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
class ConcurrencyController {
constructor(limit) {
this.limit = limit;
this.running = 0;
this.queue = [];
}
async add(promiseFactory) {
return new Promise((resolve, reject) => {
this.queue.push({ promiseFactory, resolve, reject });
this.#tryRun();
});
}
#tryRun() {
if (this.running >= this.limit || this.queue.length === 0) return;
const { promiseFactory, resolve, reject } = this.queue.shift();
this.running++;
promiseFactory()
.then(resolve)
.catch(reject)
.finally(() => {
this.running--;
this.#tryRun();
});
}
}
// 使用
const controller = new ConcurrencyController(3);
const results = await Promise.all(
urls.map(url => controller.add(() => fetch(url).then(r => r.json())))
);
注意关键细节
- 不要用
Promise.all直接包裹所有请求——它会一次性发起全部,失去控制力 - 错误处理要统一:建议每个任务都
.catch或用try/catch包裹,避免某个失败导致整个池中断 - 任务应是“函数”,不是已执行的 Promise;否则无法延迟执行,起不到限流作用
- 如果需按原始顺序返回结果,可在任务中记录索引,最后按序整理
进阶:用 p-limit 等成熟库(推荐生产环境)
npm 上的 p-limit 库经过充分测试,API 简洁:
import pLimit from 'p-limit'; const limit = pLimit(3); const promises = urls.map(url => limit(() => fetch(url).then(r => r.json()))); const results = await Promise.all(promises);
它内部做了边界处理、类型校验和性能优化,比手写更稳妥。

















