Promise并发控制 - EricYangXD/LearnReact GitHub Wiki

class Schedule{

    constructor(maxNum){
        this.list = [];
        this.maxNum = maxNum
        this.workingNum = 0
    }
    
    add(promiseCreator){
        this.list.push(promiseCreator)
    }

    start(){
        for (let index = 0; index < this.maxNum; index++) {
            this.doNext()
        }
    }

    doNext(){
        if(this.list.length && this.workingNum < this.maxNum){
            this.workingNum++;
            const promise = this.list.shift();
            promise().then(()=>{
                this.workingNum--;
                this.doNext();
            })

        }
    }
}

const timeout = time => new Promise((resolve)=>{
    setTimeout(resolve, time)
}) 

const schedule = new Schedule(2);

const addTask = (time, order)=>{
    schedule.add(()=>timeout(time).then(()=>{
        console.log(order);
    }))
}

addTask(1000, 1)
addTask(500, 2)
addTask(300, 3)
addTask(400, 4)

schedule.start()


async function asyncPool(poolLimit, array, iteratorFn) {
  const ret = []; // 存储所有的异步任务
  const executing = []; // 存储正在执行的异步任务
  for (const item of array) {
    // 调用iteratorFn函数创建异步任务
    const p = Promise.resolve().then(() => iteratorFn(item, array));
    ret.push(p); // 保存新的异步任务

    // 当poolLimit值小于或等于总任务个数时,进行并发控制
    if (poolLimit <= array.length) {
      // 当任务完成后,从正在执行的任务数组中移除已完成的任务
      const e = p.then(() => executing.splice(executing.indexOf(e), 1));
      executing.push(e); // 保存正在执行的异步任务
      if (executing.length >= poolLimit) {
        await Promise.race(executing); // 等待较快的任务执行完成
      }
    }
  }
  return Promise.all(ret);
}

function asyncPool(poolLimit, array, iteratorFn) {
  let i = 0;
  const ret = []; // 存储所有的异步任务
  const executing = []; // 存储正在执行的异步任务
  const enqueue = function () {
    if (i === array.length) {
      return Promise.resolve();
    }
    const item = array[i++]; // 获取新的任务项
    const p = Promise.resolve().then(() => iteratorFn(item, array));
    ret.push(p);

    let r = Promise.resolve();

    // 当poolLimit值小于或等于总任务个数时,进行并发控制
    if (poolLimit <= array.length) {
      // 当任务完成后,从正在执行的任务数组中移除已完成的任务
      const e = p.then(() => executing.splice(executing.indexOf(e), 1));
      executing.push(e);
      if (executing.length >= poolLimit) {
        r = Promise.race(executing); 
      }
    }
 
    // 正在执行任务列表 中较快的任务执行完成之后,才会从array数组中获取新的待办任务
    return r.then(() => enqueue());
  };
  return enqueue().then(() => Promise.all(ret));
}