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

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

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

相关推荐
自信阿杜8 分钟前
跨标签页数据同步完全指南:如何选择最优通信方案
前端·javascript
牛马11117 分钟前
WidgetsFlutterBinding.ensureInitialized()在 Flutter Web 端启动流程的影响
java·前端·flutter
Captaincc18 分钟前
2025: The year in LLMs
前端·vibecoding
指尖跳动的光36 分钟前
Vue的nextTick()方法
前端·javascript·vue.js
码事漫谈1 小时前
可能,AI早都觉醒了
前端
qq_406176142 小时前
JS 事件循环(Event Loop)
开发语言·前端·javascript
Codebee2 小时前
ooder A2UI ES6版本正式发布:现代化模块架构,MIT开源许可
前端
Devin_chen2 小时前
4.前端使用Node + MongoDB + Langchain消息管理与聊天历史存储
前端·langchain
前端er小芳2 小时前
前端文件 / 图片核心 API 全解析:File、FileReader、Blob、Base64、URL
前端
twl2 小时前
探索Agent RAG: 一文讲清楚从理论到具体落地
前端