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

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

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

相关推荐
Hello--_--World12 分钟前
ES13:类私有属性和方法、顶层 await、at() 方法、Object.hasOwnProperty()、类静态块 相关知识点
开发语言·javascript·es13
comerzhang65533 分钟前
Web 性能的架构边界:跨线程信令通道的确定性分析
javascript·webassembly
Hooray36 分钟前
为了在 Vue 项目里用上想要的 React 组件,我写了这个 skill
前端·ai编程
咸鱼翻身了么38 分钟前
模仿ai数据流 开箱即用
前端
风花雪月_38 分钟前
🔥IntersectionObserver:前端性能优化的“隐形监工”
前端
Bigger38 分钟前
告别 AI 塑料感:我是如何用 frontend-design skill 重塑项目官网的
前端·ai编程·trae
发际线向北38 分钟前
0x02 Android DI 框架解析之Hilt
前端
Ruihong39 分钟前
Vue v-bind 转 React:VuReact 怎么处理?
vue.js·react.js·面试
zhensherlock1 小时前
Protocol Launcher 系列:Overcast 一键订阅播客
前端·javascript·typescript·node.js·自动化·github·js
liangdabiao1 小时前
开源AI拼豆大升级 - 一键部署cloudflare page - 全免费 web和小程序
前端·人工智能·小程序