1-限制并发

142 阅读1分钟

并发的定义&为什么需要控制并发

并发在前端一般是指多个请求一起发送,这样可能就会造成后端压力过大。所以我们才需要控制并发数量。

控制并发的思路

比如现在有10条请求,我们限制最大的并发数为3,那么思路就为: 1. 先定好3个位置。 2. 执行3条请求。 3. 看那一条执行完毕了,再把没有执行的请求push进去执行。 4. 一直重复步骤3直到所有请求执行完成。

具体实现代码

// iLimt: 并发的数量
      function limitFn(iLimt) {
        const queue = []; // 队列
        let iActive = 0; // 正在执行的请求数量

        const next = () => {
          iActive = iActive - 1;
          if (queue.length) {
            queue.shift()();
          }
        };

        const run = async (fn, resolve, ...args) => {
          iActive = iActive + 1;

          const result = await fn(...args);
          resolve(result);
          next();
        };

        const enqueue = (fn, resolve, ...args) => {
          queue.push(run.bind(null, fn, resolve, ...args)); // bind函数会返回一个新的函数
          // 如果 小于最大并发数 && 还有请求没执行完
          if (iActive < iLimt && queue.length) {
            queue.shift()(); // 请求出队并执行
          }
        };

        const generator = (fn, ...args) => {
          return new Promise((resolve) => {
            enqueue(fn, resolve, ...args);
          });
        };

        // 暴露内部属性给外界
        Object.defineProperties(generator, {
          iActive: {
            get: () => iActive,
          },
          pendingCount: {
            get: () => queue.length,
          },
          clearQueue: {
            value: () => {
              queue.length = 0;
            },
          },
        });
        return generator;
      }

      // 最大并发数 2
      const generator = limitFn(2);

      const fetchFn = (delay, index) => {
        return new Promise((resolve) => {
          console.log(index);
          setTimeout(() => {
            resolve(index);
          }, delay);
        });
      };

      const promises = [
        generator(() => fetchFn(1000, 1)),
        generator(() => fetchFn(1000, 2)),
        generator(() => fetchFn(1000, 3)),
        generator(() => fetchFn(1000, 4)),
        generator(() => fetchFn(1000, 5)),
        generator(() => fetchFn(1000, 6)),
      ];

      Promise.all(promises);