JS异步控制流及async实现细节分析(2)

446 查看

4. map/filter/reject

在async中,each系列的方法一共有12个:

  • each/forEach
  • eachOf/forEachOf
  • eachLimit/forEachLimit
  • eachOfLimit/forEachOfLimit
  • eachSeries/forEachSeries
  • eachOfSeries/forEachOfSeries

这些方法的回调函数签名为callback(err),只有一个参数表示是否出错,因此无法收集到每个异步任务的结果。如果我们希望如下调用:

考虑到对于数组而言,可以通过forEach来实现map功能,例如:

因此,在这里,可以通过async.eachOf来实现map,代码逻辑如下:

同样,mapLimitmapSeries也可以通过类似的方式实现。

filter功能的实现也是类似的方式,例如我们希望过滤出所有存在的文件,期望的调用方式如下:

filter的实现如下:

同样,filterLimitfilterSeries也可以通过类似的方式实现。

reject的实现与filter几乎一样,除了判断条件不同之外,在async中的源码如下:

5. some/every/detect

some实现逻辑如下:

every与此类似,实现逻辑如下:

detect返回的是第一个执行为truthy的值,与some非常类似,只需要将cb(true)cb(false)分别替换为cb(val)cb(undefined)即可。

6. reduce/reduceRight

reducereduceRight主要通过async.eachOfSeries来实现,注意reduce相关的只有一个series版本,即只有串行执行的版本,因为涉及到reduce的操作往往是要依赖于上一次操作的返回值,因此不能够并行执行。

这部分源码比较简单,不做赘述。

7. sortBy

sortBy的思路是:

  • 首先通过async.map将数组映射为一个新的数组,新数组中得每一项结构为{value: x, criteria: criteria}
    • x为原数组中的元素
    • criteria为需要比较的标准
  • 新的数组会作为第二个参数传给async.map的回调函数,在该回调函数中,以criteria对新数组进行排序
  • 从排好序的数组中收集所有的value作为最终的结果集传递给sortBy的回调函数