🐋asyncEach源码分析

204 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动~

asyncEach是如何实现的呢?
如何知道异步任务执行结束?
如何函数内部和外部相互传值,控制整个流程?......

想知道以上问题的答案吗,请enjoy本文吧~
🥳🥳🥳P.S. 欢迎点赞,评论,收藏~
🥳🥳🥳如有不足,欢迎指正哦~

asyncEach

执行数组中的每一项(可以是同步也可以是异步),当有一个报错或者全部成功时,执行回调函数

实现

确定参数

array:得接受一个数组,以致可以循环执行

iterator:只有循环的对象还不行,还得有使用该对象的函数,类似个executor,那这个函数应交给用户来自定义,但是主控流程需要对这个executor进行封装,传入自己的一些方法,来实现内外沟通

callback:回调函数,当全部数组执行完毕或者有失败的情况下调用

执行过程

这个asyncEach的执行过程,如下:

image.png

源码分析

  • 对传入的变量进行校验
// items 为Array, next为iterator function, callback就是回调函数
if (!Array.isArray(items)) throw new TypeError('each() expects array as first argument');
if (typeof next !== 'function') throw new TypeError('each() expects function as second argument');
if (typeof callback !== 'function') callback = Function.prototype; // no-op
// 数组长度为0时,直接执行回调
if (items.length === 0) return callback(undefined, items);
  • 循环数组,对每一项执行iterator方法,iterator方法的参数为当前项的值一个回调函数,当前项的值用于内部告诉外部当前数据信息,回调函数用于外部告诉内部自己的执行结果(error or success or 处理后的数据 etc.),把函数的执行过程向终点推进
items.forEach(function(item, index) {
  next(item, cb);
});

var transformed = new Array(items.length);
function cb(error, transformedItem) {
    if (returned) return;
    if (error) {
      returned = true;
      return callback(error);
    }
    transformed[index] = transformedItem;
    count += 1;
    if (count === items.length) return callback(undefined, transformed);
}
  • 记录当前执行状态,判断是否已经return过,或者是否count大于等于array的长度, 然后去执行相应操作
var count = 0;
var returned = false;

if (returned) return;
if (count === items.length){}

全部源码

image.png

使用

var each = require('async-each');
each(['a.js', 'b.js', 'c.js'], fs.readFile, function(error, contents) {
  if (error) console.error(error);
  console.log('Contents for a, b and c:', contents);
});