JavaScript中的Promise并发控制与实现
字数 667 2025-11-29 16:49:58
JavaScript中的Promise并发控制与实现
描述
Promise并发控制是JavaScript异步编程中的重要概念,指在同时处理多个异步任务时,限制同时执行的任务数量,避免资源过度占用。常见场景包括控制API请求并发数、文件上传限制等。核心需求是:有N个异步任务,但最多同时执行K个,完成一个再补充下一个。
解题过程
1. 问题分析
- 假设有多个异步任务(如API请求),全部直接并发可能导致服务器压力过大或浏览器限制
- 需要实现一个控制器,支持:
- 设置并发上限(如最多3个同时进行)
- 自动调度任务:当有任务完成时,立即启动下一个等待任务
- 返回所有任务的结果(保持顺序或按完成顺序)
2. 基础实现方案
class PromisePool {
constructor(maxConcurrent) {
this.maxConcurrent = maxConcurrent; // 最大并发数
this.running = 0; // 当前运行任务数
this.queue = []; // 等待队列
}
add(task) {
return new Promise((resolve, reject) => {
this.queue.push({ task, resolve, reject });
this._run();
});
}
_run() {
// 队列为空或已达并发上限时停止
if (this.queue.length === 0 || this.running >= this.maxConcurrent) {
return;
}
this.running++;
const { task, resolve, reject } = this.queue.shift();
task()
.then(resolve, reject)
.finally(() => {
this.running--;
this._run(); // 任务完成后触发下一个任务
});
}
}
关键点说明:
add方法将任务包装为Promise并入队_run方法检查条件并执行任务- 任务完成后通过
finally递减计数并递归调用_run
3. 功能完善
基础版本缺乏批量添加和结果收集,改进如下:
class AdvancedPromisePool {
constructor(maxConcurrent) {
this.maxConcurrent = maxConcurrent;
this.running = 0;
this.queue = [];
this.results = []; // 存储任务结果
}
async runAll(tasks) {
return new Promise((resolve) => {
tasks.forEach((task, index) => {
this._add(task, index, resolve);
});
});
}
_add(task, index, resolve) {
this.queue.push({ task, index });
this._run(resolve);
}
_run(resolve) {
while (this.queue.length > 0 && this.running < this.maxConcurrent) {
this.running++;
const { task, index } = this.queue.shift();
task()
.then(result => {
this.results[index] = result; // 按原始顺序存储结果
})
.catch(error => {
this.results[index] = { error }; // 错误处理
})
.finally(() => {
this.running--;
this._run(resolve);
// 所有任务完成时解析主Promise
if (this.running === 0 && this.queue.length === 0) {
resolve(this.results);
}
});
}
}
}
// 使用示例
const pool = new AdvancedPromisePool(2);
const tasks = [1000, 2000, 3000, 4000].map(ms => () =>
new Promise(resolve => setTimeout(() => resolve(ms), ms))
);
pool.runAll(tasks).then(results => console.log(results));
// 输出: [1000, 2000, 3000, 4000](按任务顺序)
4. 进阶优化
- 动态任务添加:支持在运行中继续添加任务
- 优先级控制:通过队列排序实现高优先级任务提前执行
- 暂停/继续:增加状态标志位控制任务调度
- 超时处理:为每个任务配置超时时间,避免长时间阻塞
5. 实际应用场景
- 控制图片懒加载的并发请求数
- 批量上传文件时限制同时上传数量
- 爬虫程序中限制并发请求避免被封IP
总结
Promise并发控制通过队列管理+递归调度实现,核心是平衡并发数与系统资源。实际开发中可使用现成库(如p-limit),但理解原理有助于处理更复杂的异步流程控制场景。