100个接口如何控制并发请求

17 阅读1分钟
// 100个接口控制并发
type promiseFun = () => Promise<number>
const requestList: promiseFun[] = [] //接口列表

//模拟生成100个异步接口
for (let i = 1; i <= 100; i++) {
  requestList.push(() => {
    return new Promise((resolve) => {
      setTimeout(() => {
        console.log("接口请求完成");
        resolve(i)
      }, Math.random() * 1000)
    })
  })
}

第一种方法
const concurrenceRun = async (requestList: promiseFun[], max: number) => {
  const runList: promiseFun[][] = []
  for (let i = 0; i < requestList.length; i += max) {
    console.log(i);
    runList.push(requestList.slice(i, max + i))
  }

  for (let i = 0; i < runList.length; i++) {
    const res = await Promise.allSettled(runList[i].map(fn => fn()))
    console.log(res);
  }

}
concurrenceRun(requestList, 5)

//墙裂推荐
第二种方法 
// 运行池
const pool = new Set();

// 等待队列
const waitQueue:Function[] = [];

/**
 * @description: 限制并发数量的请求
 * @param {*} reqFn:请求方法
 * @param {*} max:最大并发数
 */
const request = (reqFn:promiseFun, max:number) => {
  return new Promise((resolve, reject) => {
    // 判断运行池是否已满
    const isFull = pool.size >= max;

    // 包装的新请求
    const newReqFn = () => {
      reqFn()
        .then(res => {
          resolve(res);
        })
        .catch(err => {
          reject(err);
        })
        .finally(() => {
          // 请求完成后,将该请求从运行池中删除
          pool.delete(newReqFn);
          // 从等待队列中取出一个新请求放入等待运行池执行
          const next = waitQueue.shift();
          if (next) {
            pool.add(next);
            next();
          }
        });
    };

    if (isFull) {
      // 如果运行池已满,则将新的请求放到等待队列中
      waitQueue.push(newReqFn);
    } else {
      // 如果运行池未满,则向运行池中添加一个新请求并执行该请求
      pool.add(newReqFn);
      newReqFn();
    }
  });
};

requestList.forEach(async item => {
  const res = await request(item, 10);
  console.log(res);
});