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

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

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

相关推荐
持久的棒棒君2 小时前
npm安装electron下载太慢,导致报错
前端·electron·npm
渔舟唱晚@3 小时前
大模型数据流处理实战:Vue+NDJSON的Markdown安全渲染架构
vue.js·大模型·数据流
crary,记忆4 小时前
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
前端·webpack·angular·angular.js
漂流瓶jz4 小时前
让数据"流动"起来!Node.js实现流式渲染/流式传输与背后的HTTP原理
前端·javascript·node.js
SamHou05 小时前
手把手 CSS 盒子模型——从零开始的奶奶级 Web 开发教程2
前端·css·web
我不吃饼干5 小时前
从 Vue3 源码中了解你所不知道的 never
前端·typescript
开航母的李大5 小时前
【中间件】Web服务、消息队列、缓存与微服务治理:Nginx、Kafka、Redis、Nacos 详解
前端·redis·nginx·缓存·微服务·kafka
Bruk.Liu5 小时前
《Minio 分片上传实现(基于Spring Boot)》
前端·spring boot·minio
鱼樱前端6 小时前
Vue3+d3-cloud+d3-scale+d3-scale-chromatic实现词云组件
前端·javascript·vue.js
q_19132846956 小时前
基于Springboot+Vue的办公管理系统
java·vue.js·spring boot·后端·intellij idea