实现一个简化版具有并发限制的顺序Promise执行器

105 阅读1分钟

直接上代码,后面再补充解释。

简化版,具有并发控制,顺序执行,返回一个promise等待所有任务完成后执行回调。

class PQueue {
  constructor(concurrency = 1) {
    this.concurrency = concurrency;
    this.runningCount = 0;
    this.queue = [];
    this.onIdleResolve = null;
  }

  add(task) {
    return new Promise((resolve, reject) => {
      const taskWrapper = async () => {
        try {
          const result = await task();
          resolve(result);
        } catch (error) {
          reject(error);
        } finally {
          this.runningCount--;
          this.dequeue();
        }
      };

      this.queue.push(taskWrapper);
      this.dequeue();
    });
  }

  dequeue() {
    if (this.runningCount >= this.concurrency) {
      return;
    }

    if (this.queue.length === 0) {
      if (this.runningCount === 0 && this.onIdleResolve) {
        this.onIdleResolve();
      }
      return;
    }

    const task = this.queue.shift();
    this.runningCount++;
    task();
  }

  onIdle() {
    return new Promise((resolve) => {
      if (this.runningCount === 0 && this.queue.length === 0) {
        resolve();
      } else {
        this.onIdleResolve = resolve;
      }
    });
  }
}

使用,参考p-queue原理实现的,所以使用也相似

const PQueue = require('p-queue');

// 创建PQueue实例,并设置最大并发数
const queue = new PQueue({ concurrency: 2 });

// 添加任务到队列
queue.add(() => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Task 1');
      resolve();
    }, 1000);
  });
});

queue.add(() => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Task 2');
      resolve();
    }, 500);
  });
});

queue.add(() => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Task 3');
      resolve();
    }, 800);
  });
});

// 执行任务队列
queue.onIdle().then(() => {
  console.log('All tasks completed');
});

加入了优先级版本。

class PQueue {
  constructor(concurrency = 1) {
    this.concurrency = concurrency;
    this.runningCount = 0;
    this.queue = [];
    this.onIdleResolve = null;
  }

  add(task, priority = 0) {
    return new Promise((resolve, reject) => {
      const taskWrapper = async () => {
        try {
          const result = await task();
          resolve(result);
        } catch (error) {
          reject(error);
        } finally {
          this.runningCount--;
          this.dequeue();
        }
      };

      const taskItem = { task: taskWrapper, priority };
      this.insertTaskWithPriority(taskItem);
      this.dequeue();
    });
  }

  insertTaskWithPriority(taskItem) {
    let inserted = false;

    for (let i = 0; i < this.queue.length; i++) {
      if (taskItem.priority > this.queue[i].priority) {
        this.queue.splice(i, 0, taskItem);
        inserted = true;
        break;
      }
    }

    if (!inserted) {
      this.queue.push(taskItem);
    }
  }

  dequeue() {
    if (this.runningCount >= this.concurrency) {
      return;
    }

    if (this.queue.length === 0) {
      if (this.runningCount === 0 && this.onIdleResolve) {
        this.onIdleResolve();
      }
      return;
    }

    const taskItem = this.queue.shift();
    this.runningCount++;
    taskItem.task();
  }

  onIdle() {
    return new Promise((resolve) => {
      if (this.runningCount === 0 && this.queue.length === 0) {
        resolve();
      } else {
        this.onIdleResolve = resolve;
      }
    });
  }
}

使用

queue.add(() => {
  // 任务逻辑...
}, 1);  // 优先级为1

queue.add(() => {
  // 任务逻辑...
}, 2);  // 优先级为2