前端限制并发n个异步函数的执行队列

230 阅读1分钟
class MyPromise {
  private promiseQueue: (() => Promise<any> | null)[]
  private _limit = 5
  private _runningNum = 0
  constructor() {
    this.promiseQueue = []
  }
  public get limit() {
    return this._limit
  }

  public set limit(n: number) {
    this._limit = n;
  }

  run(fns: (() => Promise<any> | null)[]) {
    for (let i = this._runningNum; i < this._limit; i++) {
      this._runningNum++;
      const fn = fns.shift()
      this.emit(fn).then(() => {
        this._runningNum--
        this.goes()
      })
    }
    this.promiseQueue.push(...fns);
    return this;
  }

  goes() {
    if (this._runningNum === this._limit) {
      return;
    }
    if (this.promiseQueue.length) {
      const fn = this.promiseQueue.shift()
      this._runningNum++;
      this.emit(fn).then(() => {
        this._runningNum--
        this.goes()
      })
    }
  }

  push(fns) {
    this.run(fns)
    return this;
  }
  async emit(fn: () => Promise<any>) {
    const result = await fn();
    console.log(result, this._runningNum)
    // console.log(this.promiseQueue)
    return result
  }
}

const a = () => new Promise(r => setTimeout(() => { r("a") }, 0))
const b = () => new Promise(r => setTimeout(() => { r("b") }, 0))
const c = () => new Promise(r => setTimeout(() => { r("c") }, 0))
const d = () => new Promise(r => setTimeout(() => { r("d") }, 0))
const e = () => new Promise(r => setTimeout(() => { r("e") }, 1000))
const f = () => new Promise(r => setTimeout(() => { r("f") }, 2000))
new MyPromise().run([a, e, f, b, d, c, c, c, c, e, d])
  .push([a, e, f, b, d, c])

199a631ba99a259fb66444eec4990b1.png