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),但理解原理有助于处理更复杂的异步流程控制场景。

JavaScript中的Promise并发控制与实现 描述 Promise并发控制是JavaScript异步编程中的重要概念,指在同时处理多个异步任务时,限制同时执行的任务数量,避免资源过度占用。常见场景包括控制API请求并发数、文件上传限制等。核心需求是:有N个异步任务,但最多同时执行K个,完成一个再补充下一个。 解题过程 1. 问题分析 假设有多个异步任务(如API请求),全部直接并发可能导致服务器压力过大或浏览器限制 需要实现一个控制器,支持: 设置并发上限(如最多3个同时进行) 自动调度任务:当有任务完成时,立即启动下一个等待任务 返回所有任务的结果(保持顺序或按完成顺序) 2. 基础实现方案 关键点说明 : add 方法将任务包装为Promise并入队 _run 方法检查条件并执行任务 任务完成后通过 finally 递减计数并递归调用 _run 3. 功能完善 基础版本缺乏批量添加和结果收集,改进如下: 4. 进阶优化 动态任务添加 :支持在运行中继续添加任务 优先级控制 :通过队列排序实现高优先级任务提前执行 暂停/继续 :增加状态标志位控制任务调度 超时处理 :为每个任务配置超时时间,避免长时间阻塞 5. 实际应用场景 控制图片懒加载的并发请求数 批量上传文件时限制同时上传数量 爬虫程序中限制并发请求避免被封IP 总结 Promise并发控制通过队列管理+递归调度实现,核心是平衡并发数与系统资源。实际开发中可使用现成库(如 p-limit ),但理解原理有助于处理更复杂的异步流程控制场景。