并行限制的 Promise 调度器

187 阅读1分钟
class Scheduler {
  constructor(maxConcurrent) {
    this.maxConcurrent = maxConcurrent;
    this.queue = [];
    this.currentCount = 0;
  }

  add(promise) {
    return new Promise((resolve, reject) => {
      this.queue.push(() => promise().then(resolve).catch(reject));
      this.run();
    });
  }

  run() {
    if (this.currentCount < this.maxConcurrent) {
      const task = this.queue.shift();
      if (task) {
        this.currentCount++;
        task().finally(() => {
          this.currentCount--;
          this.run();
        });
      }
    }
  }
}

// Example usage:
const scheduler = new Scheduler(2);

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

function task(id) {
  console.log(`Task ${id} started`);
  return delay(1000).then(() => {
    console.log(`Task ${id} completed`);
  });
}

for (let i = 0; i < 5; i++) {
  scheduler.add(() => task(i));
}

具体的实现思路如下:

  • 定义一个 Scheduler 类来实现 Promise 调度器。
  • Scheduler 类的构造函数接受一个参数 maxConcurrent,用来限制并行执行的 Promise 数量。
  • Scheduler 类中定义一个队列 queue,用来保存待执行的 Promise。
  • Scheduler 类中定义一个变量 currentCount,用来记录当前正在执行的 Promise 数量。
  • Scheduler 类中定义一个 add 方法,该方法接受一个 Promise 生成器函数 promise,返回一个新的 Promise。
  • add 方法中,首先将 promise 生成器函数封装成一个新的 Promise,然后将其添加到队列 queue 中。
  • add 方法中,调用 run 方法来执行队列中的 Promise。
  • Scheduler 类中定义一个 run 方法,用来执行队列中的 Promise。
  • run 方法中,首先检查当前正在执行的 Promise 数量是否小于并行限制数 maxConcurrent,如果小于,则从队列 queue 中取出一个 Promise 并执行。
  • run 方法中,每当一个 Promise 完成执行后,将 currentCount 减 1,并再次执行 run 方法,以便执行队列中的下一个 Promise。
  • run 方法中,每当一个 Promise 开始执行时,将 currentCount 加 1。

这种实现方式使用了队列来限制并行执行的 Promise 数量,通过一个队列来保存待执行的 Promise,然后通过递归执行队列中的 Promise 来实现并行限制的效果。这样就可以确保同时最多只有 maxConcurrent 个 Promise 在执行,从而避免了因过多的并行执行而导致的性能问题。