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

这段代码实现了一个 并发控制的任务执行器 ,通过 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 返回。

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

相关推荐
码农捻旧29 分钟前
前端性能优化:从之理论到实践的破局道
前端·性能优化
3Katrina30 分钟前
前端面试之防抖节流(一)
前端·javascript·面试
kk_stoper30 分钟前
使用Ruby接入实时行情API教程
java·开发语言·javascript·数据结构·后端·python·ruby
浏览器API调用工程师_Taylor42 分钟前
自动化重复任务:从手动操作到效率飞跃
前端·javascript·爬虫
赵润凤1 小时前
Vue 高级视频播放器实现指南
前端
FogLetter1 小时前
从原生JS事件到React事件机制:深入理解前端事件处理
前端·javascript·react.js
陈cCCc1 小时前
记录第一次npm发包!!!
vue.js·npm
轻语呢喃1 小时前
js事件机制:监听、捕获、冒泡与委托
javascript
小公主1 小时前
如何利用闭包封装私有变量?掌握防抖、节流与 this 问题的巧妙解决方案
前端
烛阴1 小时前
JavaScript 的动态魔法:使用 constructor 动态创建函数
前端·javascript