promise并发控制: 100个请求,控制并发最大为10个

134 阅读2分钟
  • 并发: 是在一段时间内管理和处理多个任务的能力。这并不一定意味着这些任务是在同一时刻执行的,而是指任务在同一时间段内都正在进展,它们可以交替执行。并发强调的是结构上的同时处理多个任务,例如在网络服务器中同时处理多个客户端请求。

  • 并行 并行是指两个或多个任务在同一时刻同时执行。

  • 区别: 并发和并行最关键的区别在于任务执行的同时性

问题:

100个请求,控制promise并发最大为10个...

代码的实现思路:

截屏2024-03-29 下午3.59.22.png

  1. 输入:一组返回promise的异步函数和最大并行数量
  2. 返回:返回一个promise可以获取执行结果
  3. 同步执行最大并行数
  4. 执行每个任务 结束后存储结果 依次开启下一个任务
  5. 任务全部执行完毕 并拿到对应结果后更改返回的promise状态。
/**
 * 并行最大任务
 * @param {Function[]} tasks 接收任务数组
 * @param {number} max 最大并行个数
 * @returns Promise
 */
export const concurrencyMaxTask = async (tasks = [], max = 3) => {
  let _res;
  const p = new Promise((res) => {
    _res = res;
  });

  const run = async (index) => {}; // 执行每个任务 结束后存储结果 依次开启下一个任务

  // 同步执行最大并行数
  for (let i = 0; i < max; i++) {
    run(i);
  }

  return p;
};

然后我们完善run函数

  let resList = []; // 结果数组
  let doneCount = 0; // 当前完成任务的总数量
  let index = 0; // 下一个将要被执行的任务索引
  const run = async (curIndex) => {
    if (curIndex >= tasks.length) {
      return;
    }
    tasks[curIndex]()
      .then((data) => {
        resList[curIndex] = {
          status: "succ",
          data,
        };
      })
      .catch((err) => {
        resList[curIndex] = {
          status: "fail",
          data: err,
        };
      })
      .finally(() => {
        doneCount++;
        if (doneCount >= tasks.length) {
          _res(resList);
        } else {
          run(index++);
        }
      });
  };

同时需要修改同步的for循环代码

  // 同步执行最大并行数
  for (let i = 0; i < max; i++) {
    run(index++);
  }

完整代码

export const concurrencyMaxTask = async (tasks: Task[] = [], max = 3) => {
  let _res: Resolve;
  const p = new Promise((res) => {
    _res = res;
  });

  const resList: TaskRes[] = []; // 结果数组
  let doneCount = 0; // 当前完成任务的总数量
  let index = 0; // 下一个将要被执行的任务索引
  const run = async (curIndex: number) => {
    if (curIndex >= tasks.length) {
      return;
    }
    tasks[curIndex]()
      .then((data: any) => {
        resList[curIndex] = {
          status: "succ",
          data,
        };
      })
      .catch((err: any) => {
        resList[curIndex] = {
          status: "fail",
          data: err,
        };
      })
      .finally(() => {
        doneCount++;
        if (doneCount >= tasks.length) {
          _res(resList);
        } else {
          run(index++);
        }
      });
  };

  max = Math.min(max, tasks.length);
  // 同步执行最大并行数
  for (let i = 0; i < max; i++) {
    run(index++);
  }

  return p;
};

github仓库

源码: concurrency-max-task

更多基于promise的 优化js运行时的解决方案 run-time-opti

本库长期维护更新...