欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript 中如何实现并发控制

程序员文章站 2021-12-12 11:39:00
一、并发控制简介假设有 6 个待办任务要执行,而我们希望限制同时执行的任务个数,即最多只有 2 个任务能同时执行。当 正在执行任务列表 中的任何 1 个任务完成后,程序会自动从 待办任务列表 中获取新...

一、并发控制简介

假设有 6 个待办任务要执行,而我们希望限制同时执行的任务个数,即最多只有 2 个任务能同时执行。当 正在执行任务列表 中的任何 1 个任务完成后,程序会自动从 待办任务列表 中获取新的待办任务并把该任务添加到 正在执行任务列表 中。为了让大家能够更直观地理解上述的过程,阿宝哥特意画了以下 3 张图:

1.1 阶段一

JavaScript 中如何实现并发控制

1.2 阶段二

JavaScript 中如何实现并发控制

1.3 阶段三

JavaScript 中如何实现并发控制

好的,介绍完并发控制之后,阿宝哥将以 github 上 async-pool 这个库来介绍一下异步任务并发控制的具体实现。

run multiple promise-returning & async functions with limited concurrency using native es6/es7。

二、并发控制的实现

async-pool 这个库提供了 es7 和 es6 两种不同版本的实现,在分析其具体实现之前,我们来看一下它如何使用。

2.1 asyncpool 的使用

在以上代码中,我们使用 async-pool 这个库提供的 asyncpool 函数来实现异步任务的并发控制。asyncpool 函数的签名如下所示:

该函数接收 3 个参数:

  • poollimit(数字类型):表示限制的并发数;
  • array(数组类型):表示任务数组;
  • iteratorfn(函数类型):表示迭代函数,用于实现对每个任务项进行处理,该函数会返回一个 promise 对象或异步函数。

对于以上示例来说,在使用了 asyncpool 函数之后,对应的执行过程如下所示:

通过观察以上的注释信息,我们可以大致地了解 asyncpool 函数内部的控制流程。下面我们先来分析 asyncpool 函数的 es7 实现。

2.2 asyncpool es7 实现

在以上代码中,充分利用了 promise.all 和 promise.race 函数特点,再结合 es7 中提供的 async await 特性,最终实现了并发控制的功能。利用 await promise.race(executing); 这行语句,我们会等待 正在执行任务列表 中较快的任务执行完成之后,才会继续执行下一次循环。

asyncpool es7 实现相对比较简单,接下来我们来看一下不使用 async await 特性要如何实现同样的功能。

2.3 asyncpool es6 实现

在 es6 的实现版本中,通过内部封装的 enqueue 函数来实现核心的控制逻辑。当 promise.race(executing) 返回的 promise 对象变成已完成状态时,才会调用 enqueue 函数,从 array 数组中获取新的待办任务。

三、阿宝哥有话说

在 asyncpool 这个库的 es7 和 es6 的具体实现中,我们都使用到了 promise.all 和 promise.race 函数。其中手写 promise.all 是一道常见的面试题。刚好趁着这个机会,阿宝哥跟大家一起来手写简易版的 promise.all 和 promise.race 函数。

3.1 手写 promise.all

promise.all(iterable) 方法会返回一个 promise 对象,当输入的所有 promise 对象的状态都变成 resolved 时,返回的 promise 对象就会以数组的形式,返回每个 promise 对象 resolve 后的结果。当输入的任何一个 promise 对象状态变成 rejected 时,则返回的 promise 对象会 reject 对应的错误信息。

需要注意的是对于 promise.all 的标准实现来说,它的参数是一个可迭代对象,比如 array、string 或 set 等。

3.2 手写 promise.race

promise.race(iterable) 方法会返回一个 promise 对象,一旦迭代器中的某个 promise 对象 resolved 或 rejected,返回的 promise 对象就会 resolve 或 reject 相应的值。

本文阿宝哥带大家详细分析了 async-pool 异步任务并发控制的具体实现,同时为了让大家能够更好地理解 async-pool 的核心代码。最后阿宝哥还带大家一起手写简易版的 promise.all 和 promise.race 函数。其实除了 promise.all 函数之外,还存在另一个函数 —— promise.allsettled,该函数用于解决 promise.all 存在的问题,感兴趣的小伙伴可以自行研究一下。

四、参考资源

github - async-pool
mdn - promise.all
mdn - promise.race
mdn - promise.allsettled

以上就是javascript 中如何实现并发控制的详细内容,更多关于javascript实现并发控制的资料请关注其它相关文章!