小知识,大挑战!本文正在参与“程序员必备小知识”创作活动~
asyncEach是如何实现的呢?
如何知道异步任务执行结束?
如何函数内部和外部相互传值,控制整个流程?......
想知道以上问题的答案吗,请enjoy本文吧~
🥳🥳🥳P.S. 欢迎点赞,评论,收藏~
🥳🥳🥳如有不足,欢迎指正哦~
asyncEach
执行数组中的每一项(可以是同步也可以是异步),当有一个报错或者全部成功时,执行回调函数
实现
确定参数
array:得接受一个数组,以致可以循环执行
iterator:只有循环的对象还不行,还得有使用该对象的函数,类似个executor,那这个函数应交给用户来自定义,但是主控流程需要对这个executor进行封装,传入自己的一些方法,来实现内外沟通
callback:回调函数,当全部数组执行完毕或者有失败的情况下调用
执行过程
这个asyncEach的执行过程,如下:
源码分析
- 对传入的变量进行校验
// 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){}
全部源码
使用
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);
});