JS请求并发数控制以及重发

2,534 阅读2分钟

aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAyMC8zLzkvMTcwYmQwZDBhNmQ0M2MyZA.webp 请实现如下的函数,可以批量请求数据,所有的URL地址在urls参数中,同时可以通过max参数 控制请求的并发度。当所有的请求结束后,需要执行callback回调。发请求的函数可以直接使用fetch。

作了一个重发次数的扩展

// 并发数控制且进行错误数重发
var p1 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p1'));
var p2 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p2'));
var p3 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p3'));
var p4 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p4'));
var p5 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p5'));
var p6 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p6'));
var p7 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p7'));
var p8 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p8'));
var p9 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p9'));
var p10 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p10'));
var p11 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p11'));
var p12 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p12'));
var p13 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p13'));
var p14 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p14'));
var tasks = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14];
class TaskQueue {
  /**
   * 任务队列
   * @param tasks 请求数组
   * @param maxNum 最大并发数
   * @param callTime 错误重发次数
   * @param callback 回调
   */
  constructor(tasks, maxNum, callTime, callback) {
    this.maxNum = maxNum;
    this.running = 0;
    this.queue = tasks;
    this.results = [];
    this.callback = callback;
    this.next();
    this.callTime = callTime;
  }
  next() {
    while (this.running < this.maxNum && this.queue.length) {
      console.log('running');
      const task = this.queue.shift();
      let count = 0;
      const run = async task => {
        try {
          const res = await task(task);
          console.log('success push');
          this.results.push(res);
          this.running--;
          this.next();
        } catch (e) {
          console.log('trying');
          count += 1;
          if (count >= this.callTime) {
            console.log('fail push');
            this.results.push(e);
            this.running--;
            this.next();
          } else {
            run(task);
          }
        }
      };
      run.call(this, task);
      this.running++;
    }

    if (typeof this.callback === 'function' && this.running == 0) {
      this.callback.call(null, this.results);
    }
  }
}

new TaskQueue(tasks, 4, 2, r => {
  console.log('result', r);
});
4VM28:37 running
VM28:48 trying
VM28:43 success push
VM28:37 running
VM28:48 trying
VM28:43 success push
VM28:37 running
VM28:48 trying
VM28:51 fail push
VM28:37 running
2VM28:48 trying
VM28:51 fail push
VM28:37 running
VM28:43 success push
VM28:37 running
2VM28:48 trying
VM28:51 fail push
VM28:37 running
VM28:43 success push
VM28:37 running
2VM28:48 trying
VM28:51 fail push
VM28:37 running
VM28:43 success push
VM28:37 running
2VM28:48 trying
VM28:51 fail push
VM28:37 running
VM28:43 success push
2VM28:48 trying
VM28:51 fail push
VM28:43 success push
VM28:48 trying
VM28:51 fail push
VM28:71 result (14) ["p2", "p4", "p1", "p3", "p6", "p5", "p8", "p7", "p10", "p9", "p12", "p11", "p14", "p13"]