具体分析这一段代码的逻辑

这段代码实现了一个 并发控制的任务执行器 ,通过 runParallel 函数限制并发任务的数量,从而避免一次性执行过多的任务导致系统资源耗尽。以下是对代码逻辑的具体分析。


代码分析

1. 函数定义

bash 复制代码
function runParallel(source, maxConcurrency, iteratorFn) {
  • 参数说明

    1. source:任务的来源,通常是一个数组或者可迭代对象,包含了所有需要执行的任务。
    2. maxConcurrency:最大并发数,限制同时执行的任务数量。
    3. iteratorFn:处理每个任务的函数,即每个任务的逻辑如何执行。

2. 初始化变量

ini 复制代码
const ret = []; // 存储每个任务的返回值
const executing = []; // 当前正在执行的任务的 Promise 数组
  • ret 用于存储每个任务执行的结果。
  • executing 用于跟踪当前正在执行的任务,方便控制并发数量。

3. 遍历任务

scss 复制代码
for (const item of source) {
  const p = Promise.resolve().then(() => iteratorFn(item));
  ret.push(p);
  • 核心逻辑

    • 遍历 source 中的每一个任务 item
    • 使用 Promise.resolve 确保 iteratorFn(item) 的结果是一个 Promise,无论 iteratorFn 是否同步。
    • 将任务的 Promise 存储到 ret 中,最终会通过 Promise.all(ret) 等待所有任务完成。

4. 并发控制

ini 复制代码
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= maxConcurrency) {
  await Promise.race(executing);
}
  • Promise 包装(e

    • 将当前任务 p 包装成一个新的 Promise e,在 p 完成后会将其从 executing 中移除。
    • executing.splice(executing.indexOf(e), 1):从正在执行的任务数组中移除完成的任务。
  • 控制并发数量

    • 每次将任务 e 添加到 executing 中。

    • 如果当前正在执行的任务数超过了 maxConcurrency

      • 使用 Promise.race(executing) 等待最快完成的任务结束,从而腾出并发资源。

5. 返回结果

javascript 复制代码
return Promise.all(ret);
  • Promise.all(ret) 等待所有任务完成,并返回所有任务的结果。

整体逻辑流程

  1. 遍历 source 中的任务。
  2. 为每个任务创建一个 Promise,并将其加入 retexecuting 中。
  3. 如果 executing 的长度达到 maxConcurrency,等待任意一个任务完成后继续执行下一个任务。
  4. 当所有任务都被添加到 ret 中并执行完成后,通过 Promise.all(ret) 返回所有任务的结果。

示例

假设有 5 个任务,每个任务需要 1 秒完成,并且设置最大并发数为 2:

javascript 复制代码
const source = [1, 2, 3, 4, 5];
function iteratorFn(item) {
  return new Promise((resolve) =>
    setTimeout(() => {
      console.log(`Task ${item} done`);
      resolve(item);
    }, 1000)
  );
}

runParallel(source, 2, iteratorFn).then((results) => {
  console.log("All tasks done:", results);
});

执行过程

  1. 最开始启动任务 1 和任务 2。
  2. 任务 1 或 任务 2 完成后,任务 3 开始执行。
  3. 重复上述过程,直到所有任务完成。

输出结果

bash 复制代码
Task 1 done
Task 2 done
Task 3 done
Task 4 done
Task 5 done
All tasks done: [1, 2, 3, 4, 5]

关键点

  1. 并发控制 :通过 Promise.race 实现对最大并发数的限制。
  2. 任务跟踪executing 用于追踪当前正在执行的任务。
  3. 结果收集ret 用于收集所有任务的结果,最终通过 Promise.all 返回。

这段代码是典型的 并发控制模板,适用于需要在有限资源下执行大量异步任务的场景,比如批量请求、爬虫等。

相关推荐
lecepin1 分钟前
AI Coding 资讯 2025-11-17
前端
孟祥_成都4 分钟前
下一代组件的奥义在此!headless 组件构建思想探索!
前端·设计模式·架构
灰太狼大王灬15 分钟前
Telegram 自动打包上传机器人 通过 Telegram 消息触发项目的自动打包和上传。
前端·机器人
soda_yo28 分钟前
搞不懂作用域链?这篇文章让你一眼秒懂!
javascript·面试
4***149040 分钟前
SpringSecurity登录成功后跳转问题
前端
小徐敲java42 分钟前
window使用phpStudy在nginx部署前端测试
运维·前端·nginx
Winslei44 分钟前
【hvigor专栏】OpenHarmony应用开发-hvigor插件之动态修改应用hap文件名
前端
扑棱蛾子1 小时前
前端代码一键打包上传服务器?10分钟配好永久告别手动部署!
前端·node.js
apollo_qwe1 小时前
Set 和 Map常用场景代码片段
javascript
q***T5831 小时前
前端路由懒加载实现,React与Vue
前端·vue.js·react.js