async异步流程控制模块源码

 Collections 集合处理

async.forEachOf  |  eachOf(object, iterator, callback)

  • 实现功能:遍历object对象执行iterator,报错或遍历执行完成时调用callback(error);callback(error)函数的触发时机需要手动在iterator中设置。
  • 源码解读:_keyIterator函数借用闭包遍历对象或数组(闭包中缓存数组的index值、或对象属性集合的index值),执行时获取不同的index值展开遍历,遍历终止时返回null。iterator若为异步延迟函数,每次启动执行时completed+1,延迟完成调用only_once(done)函数时completed-1,completed在源码中发挥作用没那么明确。iterator函数的尾参only_once(done)通过内部函数封装后输出给使用者,实现类似Promise模块将resolve、reject函数封装后输出给模块的调用者。callback函数在内部的执行条件是在外部调用过程中携带error错误,或者key=null、completed=0,即遍历执行完毕。
async.forEachOf =
    async.eachOf = function (object, iterator, callback) {
        callback = _once(callback || noop);
        object = object || [];

        var iter = _keyIterator(object);
        var key, completed = 0;

        while ((key = iter()) != null) {// 反复执行闭包函数iter遍历对象
            completed += 1;
            // only_once(done)中调用外部函数callback,机理同Promise-resolve相似
            // 内部函数对外部函数的影响是参数
            iterator(object[key], key, only_once(done));
        }

        if (completed === 0) callback(null);

        function done(err) {
            completed--;
            if (err) {
                callback(err);
            }
            // Check key is null in case iterator isn't exhausted
            // and done resolved synchronously.
            else if (key === null && completed <= 0) {
                callback(null);
            }
        }
    };
  • 主要问题:报错不影响后续iterator函数执行,参看async.some方法实现的中断回调的执行,捕获到err时,生成status=false状态,根据status状态调用回调函数callback。参看async.applyEach针对数组元素为函数的特殊情况,函数参数相同。
  • 官方示例:遍历读取json文件,报错或单次读取操作完成时执行callback回调,区别是携带参数为err或null。
var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
var configs = {};

async.forEachOf(obj, function (value, key, callback) {
    fs.readFile(__dirname + value, "utf8", function (err, data) {
        if (err) return callback(err);// 报错时执行callback
        try {
            configs[key] = JSON.parse(data);
        } catch (e) {
            return callback(e);
        }
        callback();// 执行完成时调用function(err)
    });
}, function (err) {
    if (err) console.error(err.message);
    // configs is now a map of JSON data
    doSomethingWith(configs);
});

 

async.forEach  |  each(arr, iterator, callback)

  • 实现功能:实现功能同async.eachOf,只是iterator函数中没有数组的index值,或者没有对象属性集合的index值。
  • 源码解读:_without函数用于去除iterator函数携带的数组index值参数。
async.forEach =
async.each = function (arr, iterator, callback) {
     return async.eachOf(arr, _withoutIndex(iterator), callback);
};
 
  • 官方示例:遍历文件信息。
async.each(openFiles, function(file, callback) {

    // Perform operation on file here.
    console.log('Processing file ' + file);

    if( file.length > 32 ) {
      console.log('This file name is too long');
      callback('File name too long');
    } else {
      // Do work to process file here
      console.log('File processed');
      callback();
    }
}, function(err) {
    // if any of the file processing produced an error, err would equal that error
    if( err ) {
      // One of the iterations produced an error.
      // All processing will now stop.
      console.log('A file failed to process');
    } else {
      console.log('All files have been processed successfully');
    }
});

 

 async.forEachOfSeries |  eachOfSeries(obj, iterator, callback)

  •  实现功能:async.eachOf对obj遍历调用的iterator函数有延迟时,同步执行该延迟。eachOfSeries方法则在一个延迟函数iterator完成后再调用下一个延迟函数iterator,实现依赖于使用者调用尾参only_once(done)函数的时机。和async.eachOf方法不同的另一点是,callback回调触发时机为捕获到错误或者遍历执行完毕时。
  • 源码解读:通过_keyIterator函数控制遍历对象或数组的节奏,在延迟执行完成后获取下一元素项执行iterator函数,或者通过完整遍历依次获取元素项执行iterator函数(async.eachOf方法中实现),通常的each方法不能做到。
async.forEachOfSeries =
    async.eachOfSeries = function (obj, iterator, callback) {
        callback = _once(callback || noop);
        obj = obj || [];
        var nextKey = _keyIterator(obj);
        var key = nextKey();
        function iterate() {
            var sync = true;
            if (key === null) {
                return callback(null);
            }
            iterator(obj[key], key, only_once(function (err) {
                if (err) {
                    callback(err);
                }
                else {
                    key = nextKey();
                    if (key === null) {
                        return callback(null);
                    } else {
                        if (sync) {
                            async.setImmediate(iterate);
                        } else {
                            iterate();
                        }
                    }
                }
            }));
            sync = false;
        }
        iterate();
    };
  • 示例:阻塞式读取文件,遍历完成或报错时打印错误消息,终止遍历。
var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
var configs = {};

async.forEachOf(obj, function (value, key, callback) {
    fs.readFile(__dirname + value, "utf8", function (err, data) {
        if (err) return callback(err);
        try {
            configs[key] = JSON.parse(data);
            callback(); // 启动下一次读取
        } catch (e) {
            return callback(e);
        }
    });
}, function (err) {
    if (err) console.error(err.message);
    // configs is now a map of JSON data
    doSomethingWith(configs);
});

 

 async.forEachSeries |  eachSeries(arr, iterator, callback)

  • 实现功能:实现功能同async.eachOfSeries,只是iterator函数中没有数组的index值,或者没有对象属性集合的index值。
  • 源码解读:_without函数用于去除iterator函数携带的数组index值参数。
async.forEachSeries =
async.eachSeries = function (arr, iterator, callback) {
    return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
};

 

  async.forEachOfLimit  |  eachOfLimit(obj, iterator, callback)

  •  实现功能:当limit=1时,eachOfLimit方法同async.eachOfSeries相似,也是上一次延时执行完成后再执行下一次延时函数,callback回调的触发时机也是报错或遍历完成后。当limit=obj.lenth(数组的长度,或对象属性集合的长度)时,eachOfLimit方法同async.eachOf相似,延时函数iterator同步执行,callback回调的触发时机是报错或遍历完成,在延时过程中报错,没法阻止下一个iterator函数的执行。limit在1和obj.length之间,limit个数的iterator同步启动,当一个延时执行完成,加载下一个iterator函数。iterator同时执行个数限制为limit。
  • 源码解读:
async.forEachOfLimit =
    async.eachOfLimit = function (obj, limit, iterator, callback) {
        _eachOfLimit(limit)(obj, iterator, callback);
    };

    function _eachOfLimit(limit) {

        return function (obj, iterator, callback) {
            callback = _once(callback || noop);
            obj = obj || [];
            var nextKey = _keyIterator(obj);
            if (limit <= 0) {
                return callback(null);
            }
            var done = false;
            var running = 0;// 记录iterator执行个数,iterator启动前+1,执行完成后-1
            var errored = false;

            (function replenish () {
                if (done && running <= 0) {
                    return callback(null);
                }

                while (running < limit && !errored) {
                    var key = nextKey();
                    if (key === null) {
                        done = true;
                        if (running <= 0) {
                            callback(null);
                        }
                        return;
                    }
                    running += 1;
                    iterator(obj[key], key, only_once(function (err) {
                        running -= 1;
                        if (err) {
                            callback(err);
                            errored = true;
                        }
                        else {
                            replenish();
                        }
                    }));
                }
            })();
        };
    }

 async.forEachLimit  |  eachLimit(arr, iterator, callback)

  • 实现功能:实现功能同async.eachOfLimit,只是iterator函数中没有数组的index值,或者没有对象属性集合的index值。
  • 源码解读:_without函数用于去除iterator函数携带的数组index值参数。
async.forEachLimit =
    async.eachLimit = function (arr, limit, iterator, callback) {
        return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
    };

  async.map  |  mapSeries  |  mapLimit(arr, iterator, callback)

  •  实现功能:async.map调用async.eachOf方法(延时函数同时执行),async.mapSeries调用async.eachOfSeries方法(延时函数逐个执行),async.mapLimit调用async.eachOfLimit方法(限制延时函数同时执行的个数)。三者均遍历obj执行iterator函数,主要目的是获取处理后的最终值results,并传给最终的回调函数callback进行处理。
  • 源码:
function doParallel(fn) {
    return function (obj, iterator, callback) {
        return fn(async.eachOf, obj, iterator, callback);
    };
}
function doParallelLimit(fn) {
    return function (obj, limit, iterator, callback) {
        return fn(_eachOfLimit(limit), obj, iterator, callback);
    };
}
function doSeries(fn) {
    return function (obj, iterator, callback) {
        return fn(async.eachOfSeries, obj, iterator, callback);
    };
}

function _asyncMap(eachfn, arr, iterator, callback) {
    callback = _once(callback || noop);
    arr = arr || [];
    var results = _isArrayLike(arr) ? [] : {};
    eachfn(arr, function (value, index, callback) {
        iterator(value, function (err, v) {
            results[index] = v;
            callback(err);
        });
    }, function (err) {
        callback(err, results);
    });
}

async.map = doParallel(_asyncMap);
async.mapSeries = doSeries(_asyncMap);
async.mapLimit = doParallelLimit(_asyncMap);
  •  源码:iterator加工获得results,并传给callback作后续处理
async.map(['file1','file2','file3'], fs.stat, function(err, results) {
    // results is now an array of stats for each file
});

async.inject  |  foldl  |  reduce(arr, memo, iterator, callback)

  •  实现功能:调用async.eachOfSeries方法(延时函数逐个执行),三者均遍历obj执行iterator函数,主要目的是处理并更新memo,并传给最终的回调函数callback进行处理。
  • 源码:
async.inject =
    async.foldl =
    async.reduce = function (arr, memo, iterator, callback) {
        async.eachOfSeries(arr, function (x, i, callback) {
            iterator(memo, x, function (err, v) {
                memo = v;// 更新memo
                callback(err);// 错误处理
            });
        }, function (err) {
            callback(err, memo);//memo不是通过传值或者闭包驻留,由上级作用域赋予
        });
    };
  •  官方示例
async.reduce([1,2,3], 0, function(memo, item, callback) {
    // pointless async:
    process.nextTick(function() {
        callback(null, memo + item) // 更新memo等
    });
}, function(err, result) {
    // result is now equal to the last value of memo, which is 6
});

 

async.foldr  |  reduceRight(arr, memo, iterator, callback)

  • 实现功能:同async.reduce相似,区别是自右向左遍历。
  • 源码解读:
async.foldr =
    async.reduceRight = function (arr, memo, iterator, callback) {
        var reversed = _map(arr, identity).reverse();
        async.reduce(reversed, memo, iterator, callback);
    };

 async.transform(arr, memo, iterator, callback)

  •  实现功能:同async.reduce方法相似,transform方法在每次延时执行完成后处理memo,等到各延时均执行完成后,调用callback获取并处理memo。transform方法内部调用async.eachOf方法,因此各延时函数近乎同一时间执行,非阻塞式实现。
  • 源码解读:
async.transform = function (arr, memo, iterator, callback) {
        if (arguments.length === 3) {
            callback = iterator;
            iterator = memo;
            memo = _isArray(arr) ? [] : {};
        }

        async.eachOf(arr, function(v, k, cb) {
            iterator(memo, v, k, cb);
        }, function(err) {
            callback(err, memo);
        });
    };
  • 官方示例:
async.transform([1,2,3], function(acc, item, index, callback) {
    // pointless async:
    process.nextTick(function() {
        acc.push(item * 2)
        callback(null)
    });
}, function(err, result) {
    // result is now equal to [2, 4, 6]
});

 

async.transform({a: 1, b: 2, c: 3}, function (obj, val, key, callback) {
    setImmediate(function () {
        obj[key] = val * 2;
        callback();
    })
}, function (err, result) {
    // result is equal to {a: 2, b: 4, c: 6}
})

 

   async.select | filter |  selectSeries | filterSeries  |  selectLimit | filterLimit(arr, iterator, callback)

  •  实现功能:async.filter调用async.eachOf方法(延时函数同时执行),async.filterSeries调用async.eachOfSeries方法(延时函数逐个执行),async.filterLimit调用async.eachOfLimit方法(限制延时函数同时执行的个数)。三者均遍历arr执行iterator函数,主要目的是iterator回调传参v过滤arr,arr的最终值是由原来的元素项构成的数组形式,arr最初为对象时,最终值由对象的键值构成数组,并将该最终值传给最终的回调函数callback进行处理。
  • 源码解读:
function _filter(eachfn, arr, iterator, callback) {
        var results = [];
        eachfn(arr, function (x, index, callback) {
            iterator(x, function (v) {
                if (v) {
                    results.push({index: index, value: x});
                }
                callback();
            });
        }, function () {
            callback(_map(results.sort(function (a, b) { // 由回调函数重置数组的元素项为results的value键值
                return a.index - b.index;
            }), function (x) {
                return x.value;
            }));
        });
    }

    // 调用async.eachOf方法遍历obj执行iterator,通过iterator的回调传参v过滤,返回数组results
    // 经过处理后,构成按序排列原元素值的数组,最终传给callback回调
    async.select =
    async.filter = doParallel(_filter);

    async.selectLimit =
    async.filterLimit = doParallelLimit(_filter);

    async.selectSeries =
    async.filterSeries = doSeries(_filter);
  •  官方示例:
async.filter(['file1','file2','file3'], function(filePath, callback) {
    fs.access(filePath, function(err) {
        callback(null, !err)
    });
}, function(err, results) {
    // results now equals an array of the existing files 以数组形式返回存在的文件
});

 

 async.reject  |  rejectSeries   |  rejectLimit(arr, iterator, callback)

  •  实现功能:与async.filter的不同之处是,async.filter方法凭借iterator的回调参数v为真值保留arr原始项,async.reject凭借v为否时保留arr原始项。
  • 源码解读:
function _reject(eachfn, arr, iterator, callback) {
        _filter(eachfn, arr, function(value, cb) {
            iterator(value, function(v) {
                cb(!v);
            });
        }, callback);
    }

    // 与async.filter的不同是,reject方法的过滤条件是,iterator的回调传参v为否值
    async.reject = doParallel(_reject);
    async.rejectLimit = doParallelLimit(_reject);
    async.rejectSeries = doSeries(_reject);

 

  • 官方示例:
async.reject(['file1','file2','file3'], function(filePath, callback) {
    fs.access(filePath, function(err) {
        callback(null, !err)
    });
}, function(err, results) {
    // results now equals an array of missing files 为不存在的文件进行后续生成文件操作
    createFiles(results);
});

 

  async.any  |  some(arr, iterator, callback)

  •  实现功能:async.any|some方法调用ansyc.eachOf方法,当arr中有一项符合条件时,回调函数获得参数即为true。回调触发时机为遍历的每个阶段arr有一项符合条件时,或者在遍历执行完成时,当遍历执行完成时触发回调函数,回调函数不携带参数。
  • 源码解读:遍历的每个阶段有符合条件项时都能触发回调的原由是,以getResult(true, x)替换eachOf方法中的err,err为真,也即触发回调。不符合条件时,err为否,也即不触发回调,除非遍历过程执行完毕。中断遍历的实现是,arr中有一项符合条件,将cb改写为false,调用callback()回调,因为没有携带参数,eachOf方法相关代码也便不执行了。
// check、getResult均为传递函数,一个转化为布尔值,一个原样输出
    function _createTester(eachfn, check, getResult) {
        return function(arr, limit, iterator, cb) {
            function done() {
                if (cb) cb(getResult(false, void 0));
            }
            function iteratee(x, _, callback) {
                if (!cb) return callback();
                // 参数function(v){}由内部函数传给外部,作为iterator的回调,执行done回调
                iterator(x, function (v) {// v由外部函数传入,x是arr的元素项
                    if (cb && check(v)) {
                        // v为真、cb存在时执行cb回调,cb和iterator都赋值为false
                        // 因为iteratee中首先判断cb是否为否值,后续遍历直接进入callback回调
                        // 进入callback回调,callback在遍历执行完成时才有意义
                        cb(getResult(true, x));
                        cb = iterator = false;
                    }
                    callback();
                });
            }
            if (arguments.length > 3) {
                eachfn(arr, limit, iteratee, done);
            } else {
                cb = iterator;
                iterator = limit;
                eachfn(arr, iteratee, done);
            }
        };
    }

    // 调用async.eachOf方法,arr参数中有一项满足条件时,回调获得结果为真
    // 回调时机为遍历的每个阶段执行完毕
    async.any =
    async.some = _createTester(async.eachOf, toBool, identity);
  • 官方示例:原示例callback首参为null,将无机会触发回调。
async.some(['file1','file2','file3'], function(filePath, callback) {
    fs.access(filePath, function(err) {
        callback(!err)
    });
}, function(result) {
    // 有一项满足条件时,result为true
    // if result is true then at least one of the files exists
});

 

  async.someLimit(arr, limit, iterator, callback)

  •  实现功能:async.someLimit方法同ansyc.some方法,只是对同时触发的iterator个数作了限制。
  • 源码解读:
async.someLimit = _createTester(async.eachOfLimit, toBool, identity);

 

 async.all  |  every(arr, iterator, callback)

  •  实现功能:async.all|every方法调用ansyc.eachOf方法,当arr中每一项符合条件时,回调函数获得参数即为true。回调触发时机为在遍历执行完成时。当遍历每个阶段执行完成时,回调函数不携带参数,因而也就不触发回调。
  • 源码解读:有一项不满足条件中断回调的原由是,cb传入否值,以及callback参数为空,回调不得执行。最末一次时,cb赋值为空,done函数不得执行,回调也不能顺利执行。
// check、getResult均为传递函数,取反
    function _createTester(eachfn, check, getResult) {
        return function(arr, limit, iterator, cb) {
            function done() {
                // cb回调为真值,遍历完成后才触发执行
                if (cb) cb(getResult(false, void 0));
            }
            function iteratee(x, _, callback) {
                if (!cb) return callback();
                // 参数function(v){}由内部函数传给外部,作为iterator的回调,执行done回调
                iterator(x, function (v) {// v由外部函数传入,x是arr的元素项
                    // v传入真值,check永远为否,cb回调不执行,callback只在遍历完成时执行
                    // v为否值,cb回调参数为否值,回调不执行
                    if (cb && check(v)) {
                        cb(getResult(true, x));
                        cb = iterator = false;
                    }
                    callback();
                });
            }
            if (arguments.length > 3) {
                eachfn(arr, limit, iteratee, done);
            } else {
                cb = iterator;
                iterator = limit;
                eachfn(arr, iteratee, done);
            }
        };
    }

    // 调用async.eachOf方法,arr参数中每一项满足条件时,回调获得结果为真
    // 回调时机为遍历执行完成时
    async.all =
    async.every = _createTester(async.eachOf, notId, notId);
  • 官方示例:原示例callback首参为null,将无机会触发回调。
async.some(['file1','file2','file3'], function(filePath, callback) {
    fs.access(filePath, function(err) {
        callback(!err)
    });
}, function(result) {
    // 每一项满足条件时,result为true
});

 

  async.everyLimit(arr, limit, iterator, callback)

  •  实现功能:async.everyLimit方法同ansyc.every方法,只是对同时触发的iterator个数作了限制。
  • 源码解读:
async.everyLimit = _createTester(async.eachOfLimit, notId, notId);

 async.detect | detectSeries (arr, iterator, callback)

 async.detectLimit (arr, iterator, callback)

  •  实现功能:async.detect方法同ansyc.some方法相同,当arr中有一项满足条件,触发回调,不同于some方法的是,some方法传递给回调函数的参数为v判断条件,detect传参为arr中第一个符合条件的元素项。detectSeries方法上一个延时函数完成后调用下一个延时函数;detectLimit方法对同时执行的迭代器iterator作了限制。
  • 源码解读:
function _findGetResult(v, x) {
        return x;
    }
    // 与some方法相同,调用了_createTester函数,差别是some传参为v判断条件,detect传参为arr的元素项
    async.detect = _createTester(async.eachOf, identity, _findGetResult);
    async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);
    async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);
  • 官方示例:
async.detect(['file1','file2','file3'], function(filePath, callback) {
    fs.access(filePath, function(err) {
        callback(!err)
    });
}, function(result) {
    // result now equals the first file in the list that exists
});

 

  async.sortBy (arr, iterator, callback)

  • 实现功能 :async.sortBy实现arr的排序,遍历执行完成后将重新排序的arr传给回调。
  • 源码解读:
// 根据用户设置的criteria排序
    async.sortBy = function (arr, iterator, callback) {
        async.map(arr, function (x, callback) {
            iterator(x, function (err, criteria) {
                if (err) {
                    callback(err);
                }
                else {
                    callback(null, {value: x, criteria: criteria});
                }
            });
        }, function (err, results) {
            if (err) {
                return callback(err);
            }
            else {
                callback(null, _map(results.sort(comparator), function (x) {
                    return x.value;
                }));
            }

        });

        function comparator(left, right) {
            var a = left.criteria, b = right.criteria;
            return a < b ? -1 : a > b ? 1 : 0;
        }
    };

 

  • 官方示例:
async.sortBy(['file1','file2','file3'], function(file, callback) {
    fs.stat(file, function(err, stats) {
        callback(err, stats.mtime);
    });
}, function(err, results,result) {
    // results is now the original array of files sorted by
    // modified date 根据修改时间排序的文件
});

 

async.sortBy([1,9,3,5], function(x, callback) {
    callback(null, x*-1);    //<- x*-1 instead of x, turns the order around
}, function(err,result) {
    // result callback
});

 

   async.concat  |  concatSeries(arr, iterator, callback)

  • 实现功能 :async.concat方法用于遍历arr执行iterator函数过程中没有报错的项
  • 源码解读:
// 拼接arr元素项传参给回调,前提是没有捕获到错误,捕获到错误则略过
    function _concat(eachfn, arr, fn, callback) {
        var result = [];
        eachfn(arr, function (x, index, cb) {
            fn(x, function (err, y) {
                result = result.concat(y || []);
                cb(err);
            });
        }, function (err) {
            callback(err, result);
        });
    }
    async.concat = doParallel(_concat);
    async.concatSeries = doSeries(_concat);

 

  • 官方示例
async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files) {
    // files is now a list of filenames that exist in the 3 directories
    // 对存在的目录名进行拼接
});

 

Controls Flow 流程管控

async.parallel  |  parallelLimit  |  series(tasks, callback)

  • 实现功能:async.parallel调用async.eachOf方法,遍历执行tasks中的任务函数,根据tasks的数据类型(数组或对象形式)构建最终值results,传给最终回调callback函数。async.parallelLimit调用async.eachOfLimit方法,async.series调用async.eachOfSeries方法,其他原理相同。tasks或者以键值对形式存储任务函数,或者以数组形式存储任务函数。results通过作用域实现在task任务函数和最终回调callback中传递。
  • 源码解读:
function _parallel(eachfn, tasks, callback) {
        callback = callback || noop;
        var results = _isArrayLike(tasks) ? [] : {};

        eachfn(tasks, function (task, key, callback) {
            task(_restParam(function (err, args) {
                if (args.length <= 1) {
                    args = args[0];
                }
                results[key] = args;// 根据tasks数据类型构建results,传给最终回调,results根据作用域传递
                callback(err);
            }));
        }, function (err) {
            callback(err, results);
        });
    }

    // 遍历执行tasks中任务函数,数组或对象形式构建results,传给回调函数callback
    async.parallel = function (tasks, callback) {
        _parallel(async.eachOf, tasks, callback);
    };

    async.parallelLimit = function(tasks, limit, callback) {
        _parallel(_eachOfLimit(limit), tasks, callback);
    };

    async.series = function(tasks, callback) {
        _parallel(async.eachOfSeries, tasks, callback);
    };

 

  • 官方示例:示例一为数组形式,数组二为对象形式。
async.parallel([
    function(callback) {
        setTimeout(function() {
            callback(null, 'one');
        }, 200);
    },
    function(callback) {
        setTimeout(function() {
            callback(null, 'two');
        }, 100);
    }
],
// optional callback
function(err, results) {
    // the results array will equal ['one','two'] even though
    // the second function had a shorter timeout.
});
// an example using an object instead of an array
async.parallel({
    one: function(callback) {
        setTimeout(function() {
            callback(null, 1);
        }, 200);
    },
    two: function(callback) {
        setTimeout(function() {
            callback(null, 2);
        }, 100);
    }
}, function(err, results) {
    // results is now equals to: {one: 1, two: 2}
});

async.applyEach  |  applyEachSeries(fns, args, callback)

  • 实现功能:async.applyEach方法调用async.eachOf遍历执行fns数组中的函数元素项,fns函数参数均相同,且为args、callback。async.applyEachSeries方法调用async.eachOfSeries,为阻塞式调用。
  • 源码解读:
 function _applyEach(eachfn) {
        return _restParam(function(fns, args) {
            var go = _restParam(function(args) {
                var that = this;
                var callback = args.pop();// 尾项为回调函数
                return eachfn(fns, function (fn, _, cb) {
                    fn.apply(that, args.concat([cb]));
                },
                callback);
            });
            if (args.length) {
                return go.apply(this, args);
            }
            else {
                return go;
            }
        });
    }

    // 调用async.eachOf遍历执行fns函数,fns函数参数均相同,且为args、callback
    async.applyEach = _applyEach(async.eachOf);
    async.applyEachSeries = _applyEach(async.eachOfSeries);

 

  • 官方示例:
async.applyEach([enableSearch, updateSchema], 'bucket', callback);

// partial application example:
async.each(
    buckets,
    async.applyEach([enableSearch, updateSchema]),
    callback
);

 

async.auto(tasks, concurrency, callback)

  •  实现功能:由tasks中处理函数获得结果results,该结果值传给最终处理函数callback作为参数,再作后续处理。特殊情况下,当tasks中任务函数需要在另一函数执行完毕后调用,async.auto会自动根据依赖关系,率先执行无依赖的任务函数,接着执行依赖函数已经执行的任务函数。当函数执行过程中报错时,最终回调callback捕获到错误err,而results由先前及本次执行函数的结果值构成。concurrency限制同时执行的任务个数。async.auto用来处理异步延时函数时,需要设置task[task.length - 1]尾项任务函数中callback回调的触发时机,进而调用依赖函数执行。
  • 源码解读:对依赖函数的处理,若tasks中任务函数无依赖时,执行task[task.length - 1](taskCallback, results),即tasks任务对象中每个键值下的尾项数组元素function(callback, results),该函数中,调用并执行taskCallback(err,result)函数,其一是更新results[k]=result输出给最终回调的参数值,其二是调用taskComplete遍历依赖函数队列listeners,加载其中依赖函数已经执行的任务函数。若tasks中任务函数有依赖时,且依赖函数尚未执行,将该任务函数存放到依赖函数队列listeners中。
// 自动以无依赖的函数到依赖执行完成的函数顺序执行函数
    // tasks以函数映射名为键,函数队列为值,尾参是处理results的回调函数
    async.auto = function (tasks, concurrency, callback) {
        if (typeof arguments[1] === 'function') {
            // concurrency is optional, shift the args.
            callback = concurrency;
            concurrency = null;
        }
        callback = _once(callback || noop);
        var keys = _keys(tasks);
        var remainingTasks = keys.length;// tasks对象共有多少键,即共多少任务

        // 没有任务,直接调用回调函数
        if (!remainingTasks) {
            return callback(null);
        }
        if (!concurrency) {
            concurrency = remainingTasks;// concurrency同时执行的任务数,默认为tasks对象有多少键
        }

        var results = {};
        var runningTasks = 0;// 跑的任务数,与concurrency比较以对同时跑的任务数作限制

        var hasError = false;

        // 需要依赖函数完成加载后才执行的函数,通过addListener方法添加到listeners队列
        // 每当一个函数加载完成,调用taskComplete执行依赖加载完成的函数项,调用removeListener更新listeners队列
        var listeners = [];
        function addListener(fn) {
            listeners.unshift(fn);
        }
        function removeListener(fn) {
            var idx = _indexOf(listeners, fn);
            if (idx >= 0) listeners.splice(idx, 1);
        }

        // remainingTasks-1,遍历listeners执行依赖加载完成的函数项
        function taskComplete() {
            remainingTasks--;
            _arrayEach(listeners.slice(0), function (fn) {
                fn();
            });
        }

        // tasks中任务函数已执行完毕的情况下,remainingTasks=0,执行最终回调函数callback
        addListener(function () {
            if (!remainingTasks) {
                callback(null, results);
            }
        });

        _arrayEach(keys, function (k) {
            if (hasError) return;
            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];

            // 因为startIndex为0,_restParam作用是将taskCallback赋值为function(err,args),处理results
            var taskCallback = _restParam(function(err, args) {
                runningTasks--;
                if (args.length <= 1) {
                    args = args[0];
                }
                if (err) {
                    var safeResults = {};
                    _forEachOf(results, function(val, rkey) {
                        safeResults[rkey] = val;
                    });
                    safeResults[k] = args;// 关于k值的驻留???
                    hasError = true;

                    // 报错直接调用最终回调函数
                    callback(err, safeResults);

                // 没有错误,执行taskComplete,遍历listeners执行依赖加载完成的函数项
                }else {
                    results[k] = args;// results由tasks的末尾项task[task.length - 1]参数带入
                    async.setImmediate(taskComplete);
                }
            });

            // 检查依赖的函数是否存在,依赖可以是数组形式,但不能依赖自身
            var requires = task.slice(0, task.length - 1);// 排除最后一项
            // prevent dead-locks
            var len = requires.length;
            var dep;
            while (len--) {
                if (!(dep = tasks[requires[len]])) {
                    throw new Error('Has nonexistent dependency in ' + requires.join(', '));
                }
                if (_isArray(dep) && _indexOf(dep, k) >= 0) {
                    throw new Error('Has cyclic dependencies');
                }
            }

            // 依赖函数x在results中,执行函数k不在results中,且同时跑的函数个数runningTasks小于限制
            function ready() {
                // _reduce遍历数组项对尾参memo作处理,迭代器函数iterator中首参为memo,次参为元素项
                return runningTasks < concurrency && _reduce(requires, function (a, x) {
                    return (a && results.hasOwnProperty(x));
                }, true) && !results.hasOwnProperty(k);
            }

            // task[task.length - 1]末尾项为函数,之前为依赖
            // taskCallback,通过调用taskComplete,遍历listeners执行依赖加载完成的函数项
            if (ready()) {
                runningTasks++;
                task[task.length - 1](taskCallback, results);
            }else {
                addListener(listener);
            }

            // 添加listeners函数队列的依赖函数,执行时runningTasks+1,删除listeners队列依赖
            function listener() {
                if (ready()) {
                    runningTasks++;
                    removeListener(listener);
                    task[task.length - 1](taskCallback, results);
                }
            }
        });
    };
 
  • 官方示例:tasks键值对任务函数末尾项参数为callback、results,官方示例写反
async.auto({
    // this function will just be passed a callback
    readData: async.apply(fs.readFile, 'data.txt', 'utf-8'),
    showData: ['readData', function(cb,results) {
        // results.readData is the file's contents
        // ...
    }]
}, callback);
 
async.auto({
    get_data: function(callback) {
        console.log('in get_data');
        // async code to get some data
        callback(null, 'data', 'converted to array');
    },
    make_folder: function(callback) {
        console.log('in make_folder');
        // async code to create a directory to store a file in
        // this is run at the same time as getting the data
        callback(null, 'folder');
    },
    write_file: ['get_data', 'make_folder', function(callback, results)) {
        console.log('in write_file', JSON.stringify(results));
        // once there is some data and the directory exists,
        // write the data to a file in the directory
        callback(null, 'filename');
    }],
    email_link: ['write_file', function(callback, results) {
        console.log('in email_link', JSON.stringify(results));
        // once the file is written let's email a link to it...
        // results.write_file contains the filename returned by write_file.
        callback(null, {'file':results.write_file, 'email':'[email protected]'});
    }]
}, function(err, results) {
    console.log('err = ', err);
    console.log('results = ', results);
});

 async.retry(times, task, callback)

  •  实现功能:task任务报错时以times设置的重置执行次数,反复调用task任务并执行,直到task任务成功时或执行到最末一个task任务时,调用最终回调函数callback。async.retry方法通过调用async.series方法实现,当times中设置了重复执行task任务的等待时间interval时,async.series方法的任务队列中添加setTimeout(fn,interval)延迟函数,fn中调用下一个任务队列函数seriesCallback(null)。成功时终止执行任务队列函数、报错时继续执行下一个任务队列函数的实现,利用async.series方法任务队列函数中内部回调函数seriesCallback传参为否时,调用下一个任务队列函数,为真时,调用最终回调。因此,当task执行成功时,seriesCallback传参为真,终止执行任务队列函数;当task任务函数执行失败时,seriesCallback传参为否,继续执行下一个任务队列函数。
  • 源码解读:
// 报错时重复尝试task任务函数,直到最末一个task任务或某个task任务执行成功时,跳向最终回调
    async.retry = function(times, task, callback) {
        var DEFAULT_TIMES = 5;
        var DEFAULT_INTERVAL = 0;

        var attempts = [];

        var opts = {
            times: DEFAULT_TIMES,// task执行次数
            interval: DEFAULT_INTERVAL// task执行完成间隙时间
        };

        function parseTimes(acc, t){
            if(typeof t === 'number'){
                acc.times = parseInt(t, 10) || DEFAULT_TIMES;
            } else if(typeof t === 'object'){
                acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;
                acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;
            } else {
                throw new Error('Unsupported argument type for \'times\': ' + typeof t);
            }
        }

        var length = arguments.length;
        if (length < 1 || length > 3) {
            throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');
        } else if (length <= 2 && typeof times === 'function') {
            callback = task;
            task = times;
        }
        if (typeof times !== 'function') {
            parseTimes(opts, times);
        }
        opts.callback = callback;
        opts.task = task;

        function wrappedTask(wrappedCallback, wrappedResults) {
            function retryAttempt(task, finalAttempt) {
                // seriesCallback为task任务执行完成后回调函数,通过async.series方法设置
                // seriesCallback首参等同async.series方法中执行函数的回调函数参数err,正常执行需为否
                // 为真跳到最终回调
                // seriesCallback在async.series方法的意义是调用下一个task或最终回调
                return function(seriesCallback) {
                    // task首参为函数,该函数中调用async.series方法seriesCallback,也就是设置回调时机
                    task(function(err, result){
                        // err为否,执行成功的前提下,跳到最终回调,结束task任务的反复执行
                        // err为真,忽略该错误,继续执行task任务
                        // 到最末一个task任务时,执行完毕即调用最终回调
                        seriesCallback(!err || finalAttempt, {err: err, result: result});
                    }, wrappedResults);
                };
            }

            // 两个task任务之间添加等待时间
            function retryInterval(interval){
                return function(seriesCallback){
                    setTimeout(function(){
                        seriesCallback(null);
                    }, interval);
                };
            }

            while (opts.times) {

                var finalAttempt = !(opts.times-=1);
                attempts.push(retryAttempt(opts.task, finalAttempt));
                // 两个task任务之间添加等待时间
                if(!finalAttempt && opts.interval > 0){
                    attempts.push(retryInterval(opts.interval));
                }
            }

            // function(done,data)作为async.series方法的最终回调,done为是否报错,data为传入数据
            async.series(attempts, function(done, data){
                // data为tasks处理获得的最终值,获取尾项,其余项为中间处理值
                data = data[data.length - 1];
                (wrappedCallback || opts.callback)(data.err, data.result);
            });
        }

        // If a callback is passed, run this as a controll flow
        // 没有callback参数项时,输出为函数,需要传递wrappedCallback与wrappedResults
        return opts.callback ? wrappedTask() : wrappedTask;
    };

 

  • 示例:
function(callback) {
        async.retry({times:5, interval:1000}, function(cb) {
            do_task();
            var some_err = '';
            var some_result = '';
            cb(some_err, some_result);// 启用下一个任务函数或最终回调
        }, function(err, result) {
            callback(err, result);
        });
    },

 

async.iterator( tasks )

  • 实现功能:async模块内部_keyIterator函数遍历数组或对象执行时机是可控。当遍历对象是数组时,执行一次,去除数组元素的首项,执行第二次,取出数组元素的第二项。async.itertor方法同该数组、对象遍历函数相似,以可控的方式遍历执行tasks函数队列。调用async.itertor方法返回tasks队列首函数的执行函数,又通过执行函数返回次函数的执行函数,构成链式调用。特别的,可以当前执行函数的next方法获取下一个任务函数的执行函数,在async.waterfall方法中有使用。内部_keyIterator函数通过闭包实现,async.itertor方法通过返回函数实现。
  • 源码解读:
// 以可控的方式遍历执行tasks函数队列
    // makeCallback构建执行函数,并作为返回值
    // 执行函数调用过程中,执行tasks的任务函数,并调用makeCallback函数构建下一个任务函数的执行函数作为返回值
    // 执行函数的next方法获取下一个任务函数的执行函数
    async.iterator = function (tasks) {
        function makeCallback(index) {
            function fn() {// 执行函数
                if (tasks.length) {
                    tasks[index].apply(null, arguments);
                }
                return fn.next();
            }
            fn.next = function () {
                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
            };
            return fn;
        }
        return makeCallback(0);
    };

 

  • 示例:
var a=async.intertor([function(){
       console.log(1)
},function(){
       console.log(2)
}]);
var b=a();// 打印1
b(); // 打印2
a.next()() // 打印2

 

 async.waterfall(tasks, callback)

  • 实现功能:async.intertor(tasks)方法为顺序执行tasks任务函数,上一个任务函数和下一个任务函数的关联只是影响执行时机,对下一个任务函数的参数无影响。async.auto(tasks, concurrency, callback)方法可以设置下一组任务函数的参数,但是最终回调函数callback的参数由多个任务函数处理值拼接后形成。async.parallel | series方法,最终回调函数获得参数同auto方法,由历次任务函数结果值拼接成数组或对象构成。比较下,async.waterfall(tasks, callback)方法也可以设置下一个任务函数的参数,并且最终回调callback的参数也由最后一个任务函数传参形成,似水珠似滚落,修改后传给下一个回调;async.auto像滚雪球,越滚越大。
  • 源码解读:
// 顺序执行tasks任务函数,并为任务函数传递参数,报错或任务函数执行完毕调用callback
    async.waterfall = function (tasks, callback) {
        callback = _once(callback || noop);
        if (!_isArray(tasks)) {
            var err = new Error('First argument to waterfall must be an array of functions');
            return callback(err);
        }
        if (!tasks.length) {
            return callback();
        }
        function wrapIterator(iterator) {
            return _restParam(function (err, args) {
                if (err) {
                    callback.apply(null, [err].concat(args));
                }
                else {
                    var next = iterator.next();// async.iterator方法获取下一个执行函数
                    if (next) {
                        args.push(wrapIterator(next));
                    }
                    else {
                        args.push(callback);
                    }
                    // 调用ensureAsync避免堆栈溢出
                    // 执行iterator函数,函数尾参为下一个iterator函数或最终回调callback
                    // 同时为下一个iterator函数或最终回调callback传递参数
                    ensureAsync(iterator).apply(null, args);
                }
            });
        }
        wrapIterator(async.iterator(tasks))();
    };

 

  •  官方示例:
async.waterfall([
    function(callback) {
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback) {
        // arg1 now equals 'one' and arg2 now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback) {
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'
});

async.whilst ( test, intertor, callback)

async.doWhilst ( intertor, test, callback)

async.until ( test, intertor, callback)

async.doUntil ( intertor, test, callback)

  • 实现功能:根据test校验结果执行intertor,test返回为真,执行intertor,test为否,执行最终回调callback。async.whilst方法和async.doWhilst方法的差别是前者可能执行也可能不执行intertor,完成看test校验结果,后者intertor必然执行一遍,随后看test校验结果。test获得参数和intertor获得参数相同,由使用者提供。until方法与whilst方法不同之处是,until方法作取反校验。
  • 源码解读:
// test合格后,执行iterator,否则跳到最终回调callback,目的是处理变量
    async.whilst = function (test, iterator, callback) {
        callback = callback || noop;
        if (test()) {
            var next = _restParam(function(err, args) {// args由外部函数传入
                if (err) {
                    callback(err);
                } else if (test.apply(this, args)) {
                    iterator(next);// 调用下一个iterator
                } else {
                    callback.apply(null, [null].concat(args));// 执行完成后最终回调,参数为null、args
                }
            });
            iterator(next);// 第一个iterator
        } else {
            callback(null);
        }
    };

    // iterator必然执行一次,其他看test检验是否合格
    async.doWhilst = function (iterator, test, callback) {
        var calls = 0;
        return async.whilst(function() {
            return ++calls <= 1 || test.apply(this, arguments);
        }, iterator, callback);
    };

    // 取反校验
    async.until = function (test, iterator, callback) {
        return async.whilst(function() {
            return !test.apply(this, arguments);
        }, iterator, callback);
    };

    async.doUntil = function (iterator, test, callback) {
        return async.doWhilst(iterator, function() {
            return !test.apply(this, arguments);
        }, callback);
    };
  • 官方示例:
var count = 0;
async.whilst(
    function() { return count < 5; },
    function(callback) {
        count++;
        setTimeout(function() {
            callback(null, count);
        }, 1000);
    },
    function (err, n) {
        // 5 seconds have passed, n = 5
    }
);

async.during ( test, intertor, callback)

async.doDuring ( intertor, test, callback)

  • 实现功能:相比whilst方法,during方法支持异步校验,test通过传递check函数作为参数的方式,校验check函数的参数是否为真,check函数的执行时机由使用者把握,whilst方法中test函数执行时机固定。
  • 源码解读:
// 同whilst,不同的是whilst方法校验立即执行,during方法校验需要等待使用者向test回调函数中注入参数
    // 可以实现异步校验,test回调参数通过延时函数获得
    async.during = function (test, iterator, callback) {
        callback = callback || noop;

        var next = _restParam(function(err, args) {
            if (err) {
                callback(err);
            } else {
                args.push(check);// args可以在同步处理或异步处理后使用
                test.apply(this, args);// args尾参中传入check,使用者调用执行
            }
        });

        var check = function(err, truth) {
            if (err) {
                callback(err);
            } else if (truth) {
                iterator(next);
            } else {
                callback(null);
            }
        };

        test(check);
    };

    async.doDuring = function (iterator, test, callback) {
        var calls = 0;
        async.during(function(next) {
            if (calls++ < 1) {
                next(null, true);
            } else {
                test.apply(this, arguments);
            }
        }, iterator, callback);
    };

 

  • 官方示例:
var count = 0;

async.during(
    function (callback) {
        // 可设置异步函数,在异步函数中执行callback校验回调,实现异步校验
        return callback(null, count < 5);
    },
    function (callback) {
        count++;
        setTimeout(callback, 1000);
    },
    function (err) {
        // 5 seconds have passed
    }
);

 

async.queue(worker, concurrency)

async.cargo(worker, payload)

  • 实现功能:async.queue添加任务函数并执行,提供暂停和重启功能。通过构建queue对象实现,任务函数在woker函数执行过程中启动。queue方法中参数concurrency用以限制同步执行的任务函数个数,cargo方法中参数concurrency设为1,即一次执行一个任务单元;cargo方法中参数payload设置预加载的任务单元中包含几个任务函数,这几条任务函数和下一个任务单元为同步执行关系,queue方法中payload设置为1,即一个任务单元只有一条任务函数。
  • 源码解读:实现过程中queue.tasks缓存待执行的任务函数,push方法调用_insert注册任务函数时添加,process执行任务单元时减少,kill方法清空,idle方法判断任务函数是否执行完毕;workers正在执行任务单元个数,process方法自增1,process方法中设置的回调函数_next函数自减1,表示该任务单元执行完成;workersList正在执行的任务单元,process方法添加,_next函数清除。unshift、push方法添加任务函数更新queue.tasks任务函数队列,并调用process方法执行任务函数;process方法设置任务单元,任务单元中包含的函数,调用worker方法执行任务函数的回调,启动下一个任务函数的执行;pause方法终止执行;resume方法恢复执行。saturated、empty、drain方法通过改写实现其功能,saturated方法当任务单元执行数量达到限制时执行,empty方法当process方法校验任务函数队列queue.tasks为空时执行,drain方法当所有任务执行完成后调用。
// 加载或执行任务函数(回调函数),任务函数的目的是启动任务函数中的回调函数
    function _queue(worker, concurrency, payload) {
        if (concurrency == null) {
            concurrency = 1;
        }
        else if(concurrency === 0) {
            throw new Error('Concurrency must not be zero');
        }
        // q.tasks待执行的任务函数队列添加任务
        function _insert(q, data, pos, callback) {// pos头部插入任务队列q.tasks
            if (callback != null && typeof callback !== "function") {
                throw new Error("task callback must be a function");
            }
            q.started = true;
            if (!_isArray(data)) {
                data = [data];
            }
            if(data.length === 0 && q.idle()) {
                // call drain immediately if there are no tasks
                return async.setImmediate(function() {
                    q.drain();
                });
            }
            _arrayEach(data, function(task) {
                var item = {
                    data: task,
                    callback: callback || noop
                };

                if (pos) {
                    q.tasks.unshift(item);
                } else {
                    q.tasks.push(item);
                }

                if (q.tasks.length === q.concurrency) {
                    q.saturated();
                }
            });
            async.setImmediate(q.process);
        }
        // 一个任务执行完成后回调,执行任务数workers-1,更新执行任务队列workersList
        // 执行任务固有的回调函数task.callback,调用执行下一个任务
        function _next(q, tasks) {
            return function(){
                workers -= 1;

                var removed = false;
                var args = arguments;
                // 更新workersList执行任务队列
                _arrayEach(tasks, function (task) {
                    _arrayEach(workersList, function (worker, index) {
                        if (worker === task && !removed) {
                            workersList.splice(index, 1);
                            removed = true;
                        }
                    });

                    // 执行任务固有的回调函数
                    task.callback.apply(task, args);
                });
                if (q.tasks.length + workers === 0) {
                    q.drain();
                }
                q.process();
            };
        }

        var workers = 0;// 执行中的任务数量
        var workersList = [];// 执行中的任务
        var q = {
            tasks: [],// 任务函数队列
            concurrency: concurrency,// 同步执行的worker个数
            payload: payload,
            saturated: noop,// 空函数,改写后实现功能,同步执行达到限制时执行
            empty: noop,// 改写实现功能,任务为空时执行
            drain: noop,// 改写实现功能,所有任务都执行完成后调用
            started: false,
            paused: false,
            push: function (data, callback) {// 尾部插入
                _insert(q, data, false, callback);
            },
            kill: function () {// 清空q.tasks任务函数队列
                q.drain = noop;
                q.tasks = [];
            },
            unshift: function (data, callback) {// 头部插入
                _insert(q, data, true, callback);
            },
            process: function () {
                while(!q.paused && workers < q.concurrency && q.tasks.length){

                    // 从q.tasks中取出任务,并更新q.tasks需要执行的任务函数队列
                    // tasks一个任务单元,任务单元中的任务同步执行
                    var tasks = q.payload ?
                        q.tasks.splice(0, q.payload) :
                        q.tasks.splice(0, q.tasks.length);// 预加载的任务函数数量

                    var data = _map(tasks, function (task) {
                        return task.data;
                    });

                    if (q.tasks.length === 0) {
                        q.empty();
                    }
                    workers += 1;
                    workersList.push(tasks[0]);
                    var cb = only_once(_next(q, tasks));
                    worker(data, cb);// _queue函数参数worker执行过程中调用cb函数执行下一个任务函数
                }
            },
            length: function () {// 需要执行的任务
                return q.tasks.length;
            },
            running: function () {// 同步执行的任务数
                return workers;
            },
            workersList: function () {// 同步执行的任务
                return workersList;
            },
            idle: function() {// 所有任务都已执行完成
                return q.tasks.length + workers === 0;
            },
            pause: function () {// 中断process函数执行
                q.paused = true;
            },
            resume: function () {// 恢复执行
                if (q.paused === false) { return; }
                q.paused = false;
                var resumeCount = Math.min(q.concurrency, q.tasks.length);
                // Need to call q.process once per concurrent
                // worker to preserve full concurrency after pause
                for (var w = 1; w <= resumeCount; w++) {
                    async.setImmediate(q.process);
                }
            }
        };
        return q;
    }

    // 返回queue对象,听过该对象添加或执行任务函数,通过调用worker函数执行任务函数
    // concurrency限制同步执行的任务个数
    async.queue = function (worker, concurrency) {
        // push进queue对象的任务函数通过调用worker执行其功能
        var q = _queue(function (items, cb) {
            worker(items[0], cb);
        }, concurrency, 1);

        return q;
    };
    
    // 返回queue对象,听过该对象添加或执行任务函数,通过调用worker函数执行任务函数
    // payload单次执行的任务单元中包含几条任务函数,这几条任务函数和下一个任务单元同步执行
    async.cargo = function (worker, payload) {
        return _queue(worker, 1, payload);
    };

 

  • 官方示例:
// create a queue object with concurrency 2
var q = async.queue(function(task, callback) {
    console.log('hello ' + task.name);
    callback();
}, 2);

// assign a callback
q.drain = function() {
    console.log('all items have been processed');
};

// add some items to the queue 添加任务函数并执行,任务函数在queue方法首参callback中执行
q.push({name: 'foo'}, function(err) {
    // 先打印task.name 即foo,后打印finished processing foo
    console.log('finished processing foo');
});
q.push({name: 'bar'}, function (err) {
    console.log('finished processing bar');
});

// add some items to the queue (batch-wise)
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
    console.log('finished processing item');
});

// add some items to the front of the queue
q.unshift({name: 'bar'}, function (err) {
    console.log('finished processing bar');
});

 

// create a cargo object with payload 2
var cargo = async.cargo(function(tasks, callback) {
    for (var i=0; i<tasks.length; i++) {
        console.log('hello ' + tasks[i].name);
    }
    callback();
}, 2);

// add some items
cargo.push({name: 'foo'}, function(err) {
    console.log('finished processing foo');
});
cargo.push({name: 'bar'}, function(err) {
    console.log('finished processing bar');
});
cargo.push({name: 'baz'}, function(err) {
    console.log('finished processing baz');
});

async.priorityQueue(worker, concurrency)

  • 实现功能:priorityQueue方法同queue方法基本相同,同时可以设置任务函数执行的优先级。priorityQueue方法内部调用queue方法,同时删除queue.unshift方法,改写queue.push方法。
  • 源码解读:通过中值法以及移位运算符将优先级较低的任务函数插到queue.tasks合适的位置值得留意
 // 内部调用async.queue方法返回queue对象,只是删除了unshift方法、改写了push方法
    // 设置任务函数执行的优先级
    async.priorityQueue = function (worker, concurrency) {

        // 比较优先级,越低越高优先级
        function _compareTasks(a, b){
            return a.priority - b.priority;
        }

        // 通过不断和拆分数组的中值作比较,得出item应该插到sequence数组中哪个位置
        function _binarySearch(sequence, item, compare) {
            var beg = -1,
                end = sequence.length - 1;
            while (beg < end) {
                var mid = beg + ((end - beg + 1) >>> 1);// 无符号右移,即除2,忽略余数
                if (compare(item, sequence[mid]) >= 0) {
                    beg = mid;
                } else {
                    end = mid - 1;
                }
            }
            return beg;
        }

        function _insert(q, data, priority, callback) {
            if (callback != null && typeof callback !== "function") {
                throw new Error("task callback must be a function");
            }
            q.started = true;
            if (!_isArray(data)) {
                data = [data];
            }
            if(data.length === 0) {
                // call drain immediately if there are no tasks
                return async.setImmediate(function() {
                    q.drain();
                });
            }
            _arrayEach(data, function(task) {
                var item = {
                    data: task,
                    priority: priority,
                    callback: typeof callback === 'function' ? callback : noop
                };

                q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);

                if (q.tasks.length === q.concurrency) {
                    q.saturated();
                }
                async.setImmediate(q.process);
            });
        }

        // Start with a normal queue
        var q = async.queue(worker, concurrency);

        // Override push to accept second parameter representing priority
        q.push = function (data, priority, callback) {
            _insert(q, data, priority, callback);
        };

        // Remove unshift function
        delete q.unshift;

        return q;
    };

  

  • 示例:
var q = async.priorityQueue(function(task, callback) {
    console.log('hello ' + task.name);
    callback();
}, 2);

q.drain = function() {
    console.log('all items have been processed');
};

q.push({name: 'foo'}, 1,function(err) {
    console.log('finished processing foo');
});
q.push({name: 'bar'},2, function (err) {
    console.log('finished processing bar');
});

q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}],3, function(err) {
    console.log('finished processing item');
});

 

async.times | timesSeries | timesLimit( times, intertor, callback)

  • 实现功能:times方法调用map方法,timesSeries调用mapSeries方法,timesLimit调用mapLimit方法,设置iterator执行次数,传参为index值,即index遍历。
  • 源码解读:
function _times(mapper) {
        return function (count, iterator, callback) {
            // _range(count)输出为0到count构成数组
            mapper(_range(count), iterator, callback);
        };
    }

    // 设置iterator的调用次数count
    async.times = _times(async.map);
    async.timesSeries = _times(async.mapSeries);
    async.timesLimit = function (count, limit, iterator, callback) {
        return async.mapLimit(_range(count), limit, iterator, callback);
    };
  • 官方示例:
// Pretend this is some complicated async factory
var createUser = function(id, callback) {
    callback(null, {
        id: 'user' + id
    });
};

// generate 5 users
async.times(5, function(n, next) {
    createUser(n, function(err, user) {
        next(err, user);
    });
}, function(err, users) {
    // we should now have 5 users
});

async.seq | compose(fns)

  • 实现功能:返回函数,函数参数传递memo,seq方法本质调用async.reduce方法实现,遍历fns函数并执行,各回调处理memo后,将memo传递给最终回调callback函数。compose反向遍历并执行fns函数。
  • 源码解读:
// async.reduce的简化方案,遍历执行函数,对传递数据作处理后传给各回调
    async.seq = function (/* functions... */) {
        var fns = arguments;
        return _restParam(function (args) {
            var that = this;

            var callback = args[args.length - 1];
            if (typeof callback == 'function') {
                args.pop();
            } else {
                callback = noop;
            }

            async.reduce(fns, args, function (newargs, fn, cb) {
                fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {
                    cb(err, nextargs);
                })]));
            },
            function (err, results) {
                callback.apply(that, [err].concat(results));
            });
        });
    };

    async.compose = function (/* functions... */) {
        return async.seq.apply(null, Array.prototype.reverse.call(arguments));
    };

官方示例:

// Requires lodash (or underscore), express3 and dresende's orm2.
// Part of an app, that fetches cats of the logged user.
// This example uses `seq` function to avoid overnesting and error
// handling clutter.
app.get('/cats', function(request, response) {
    var User = request.models.User;
    async.seq(
        _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
        function(user, fn) {
            user.getCats(fn);      // 'getCats' has signature (callback(err, data))
        }
    )(req.session.user_id, function (err, cats) {
        if (err) {
            console.error(err);
            response.json({ status: 'error', message: err.message });
        } else {
            response.json({ status: 'ok', message: 'Cats found', data: cats });
        }
    });
});

async.forever( fn, callback)

  • 实现功能:fn执行过程中,next回调执行调用fn自身,当报错时调用callback回调。
  • 源码解读:
// fn执行完毕,使用next函数,或者调用自身,或者报错时执行回调
    async.forever = function (fn, callback) {
        var done = only_once(callback || noop);
        var task = ensureAsync(fn);
        function next(err) {
            if (err) {
                return done(err);
            }
            task(next);
        }
        next();
    };
  • 官方示例:
async.forever(
    function(next) {
        // next is suitable for passing to things that need a callback(err [, whatever]);
        // it will result in this function being called again.
    },
    function(err) {
        // if next is called with a value in its first parameter, it will appear
        // in here as 'err', and execution will stop.
    }
);

Utils 工具方法

async.ensureAsync(fn)

  • 实现功能:根据fn(args,callback)是否延时函数,包装callback函数后传给fn。实现过程,ensureAsync方法接收fn的参数,改写后,再传递给fn。改写callback的目的是,当fn为同步函数时,使用async.setImmediate方法立即执行(该方法执行完成后也许立即回收堆栈),可以避免内存的浪费。
  • 源码解读:
function ensureAsync(fn) {
        // 输入参数最后一项是回调函数,sync为真同步执行状态,为否异步执行状态
        // 改写回调项,async.setImmediate跟普通调用callback的区别是没有堆栈溢出?
        return _restParam(function (args) {
            var callback = args.pop();
            args.push(function () {
                var innerArgs = arguments;
                if (sync) {
                    async.setImmediate(function () {
                        callback.apply(null, innerArgs);
                    });
                } else {
                    callback.apply(null, innerArgs);
                }
            });
            var sync = true;
            fn.apply(this, args);
            sync = false;
        });
    }

    // 改写参数函数fn中参数的回调函数callback设置,callback启动时机依然需使用者触发
    // 改写callback的目的避免同步函数的内存浪费
    async.ensureAsync = ensureAsync;

 

  • 官方示例:
function sometimesAsync(arg, callback) {
    if (cache[arg]) {
        return callback(null, cache[arg]); // this would be synchronous!!
    } else {
        doSomeIO(arg, callback); // this IO would be asynchronous
    }
}

// this has a risk of stack overflows if many results are cached in a row
// 堆栈溢出
async.mapSeries(args, sometimesAsync, done);

// this will defer sometimesAsync's callback if necessary,
// preventing stack overflows
// 避免堆栈溢出
async.mapSeries(args, async.ensureAsync(sometimesAsync), done);

async.ensureAsync(fn)

  • 实现功能:重设fn的参数。通过改造函数ensureAsync方法向fn中传递参数,返回fn的包装执行函数,该包装执行函数的参数也传给fn作为参数。
  • 源码解读:
// 返回fn的执行函数,目的是重设fn的参数
    async.apply = _restParam(function (fn, args) {
        return _restParam(function (callArgs) {
            return fn.apply(
                null, args.concat(callArgs)
            );
        });
    });
  • 官方示例:
node> var fn = async.apply(sys.puts, 'one');
node> fn('two', 'three');
one
two
three// sys.puts获得参数"one","two","three"

async.log | dir(fn,args)

  • 实现功能:在异步函数执行完成后打印结果,dir方法调用console.dir以dom视图打印。实现思路是,调用_resetParam重设fn函数的参数,最后一项为回调函数callback,其余项为log、dir方法的args,callback在内部封装后输出给外部,外部设置该回调的执行时机以及参数。
  • 源码解读:
function _console_fn(name) {
        return _restParam(function (fn, args) {
            // 通过内部函数向外部函数传递回调函数function(err,args)作为参数
            // 外部函数中设置回调函数的执行时机
            // 实际意义似乎和在异步函数中直接调用console.log()没差别
            fn.apply(null, args.concat([_restParam(function (err, args) {
                if (typeof console === 'object') {
                    if (err) {
                        if (console.error) {
                            console.error(err);
                        }
                    }
                    else if (console[name]) {
                        _arrayEach(args, function (x) {
                            console[name](x);
                        });
                    }
                }
            })]));
        });
    }
    async.log = _console_fn('log');
    async.dir = _console_fn('dir');// 显示dom试图
    /*async.info = _console_fn('info');
    async.warn = _console_fn('warn');
    async.error = _console_fn('error');*/
 
  • 官方示例:
// in a module
var hello = function(name, callback) {
    setTimeout(function() {
        callback(null, 'hello ' + name);
    }, 1000);
};

// in the node repl
node> async.log(hello, 'world');
'hello world'
 
// in a module
var hello = function(name, callback) {
    setTimeout(function() {
        callback(null, {hello: name});
    }, 1000);
};

// in the node repl
node> async.dir(hello, 'world');
{hello: 'world'}

async.memoize(fn,hasher) 

async.unmemoize(fn)

  • 实现功能:若fn已执行,且传参相同,重新调用fn的回调函数,若fn执行过程中,且fn传参相同,添加fn的回调函数。实现思路是使用queues记录fn参数下所用回调函数,执行完成时在回调函数中清空queues,当fn执行过程中,且传参相同,queues相应键值下就有值,可以做比较;在fn执行完成的回调中,使用memo记录fn参数下回调函数使用的参数,再次用同样参数执行fn时,memo相应键值下为真;初次调用作普通函数处理。memoize方法返回memoized函数。unmemoize方法将memoized函数作为普通函数处理。
  • 源码解读:
// 传参相同,fn已执行的状态下,重复调用回调函数,或fn执行中,添加回调函数
    async.memoize = function (fn, hasher) {
        var memo = {};
        var queues = {};
        var has = Object.prototype.hasOwnProperty;
        hasher = hasher || identity;
        var memoized = _restParam(function memoized(args) {
            var callback = args.pop();
            var key = hasher.apply(null, args);
            if (has.call(memo, key)) {   
                // 已执行,立即执行fn的回调
                async.setImmediate(function () {
                    callback.apply(null, memo[key]);
                });
            }
            else if (has.call(queues, key)) {
                // fn执行过程中,参数args相同,添加回调callback
                queues[key].push(callback);
            }
            else {
                queues[key] = [callback];// 执行前fn回调添加到queues队列
                fn.apply(null, args.concat([_restParam(function (args) {
                    memo[key] = args;// fn执行完成更新memo记录已执行,对象的键可以是数组、对象等数据类型
                    var q = queues[key];
                    delete queues[key];// 执行完清空该fn回调队列queues[key]
                    for (var i = 0, l = q.length; i < l; i++) {
                        q[i].apply(null, args);// 执行fn的回调
                    }
                })]));
            }
        });
        memoized.memo = memo;
        memoized.unmemoized = fn;// 没有memo记录的直接调用
        return memoized;
    };

    // 对async.memoize返回对象或普通函数fn作处理,视为普通函数处理
    async.unmemoize = function (fn) {
        return function () {
            return (fn.unmemoized || fn).apply(null, arguments);
        };
    };

 

  • 官方示例:
var slow_fn = function(name, callback) {
    // do something
    callback(null, result);
};
var fn = async.memoize(slow_fn);

// fn can now be used as if it were slow_fn   初次使用fn
fn('some name', function() {
    // callback
    console.log(1)
});

// 添加fn回调
fn('some name', function() {
    // callback
    console.log(2)
});

async.constant(value) 

  • 实现功能:使回调函数的首参err值为null,次参为value。
  • 源码解读:
// 重设callback首参err为null
    async.constant = _restParam(function(values) {
        var args = [null].concat(values);
        return function (callback) {
            return callback.apply(this, args);
        };
    });
  • 官方示例:
async.waterfall([
    async.constant(42),
    function (value, next) {
        // value === 42
    },
    //...
], callback);

async.waterfall([
    async.constant(filename, "utf8"),
    fs.readFile,
    function (fileData, next) {
        //...
    }
    //...
], callback);

async.auto({
    hostname: async.constant("https://server.net/"),
    port: findFreePort,
    launchServer: ["hostname", "port", function (options, cb) {
        startServer(options, cb);
    }],
    //...
}, callback);

 

async.wrapSync | asyncify(func) 

  • 实现功能:返回函数中传入func函数的参数(取出最末一个回调函数callback),执行func,若返回值不是带有then方法的thenable对象,直接执行回调函数callback;若返回值是thenable对象,执行该thenable对象的then方法。
  • 源码解读:
// 执行func,若返回值为thenable对象,再次执行该thenable对象的then方法,若不是,直接调用回调函数
    async.wrapSync =
    async.asyncify = function asyncify(func) {
        return _restParam(function (args) {
            var callback = args.pop();
            var result;
            try {
                result = func.apply(this, args);
            } catch (e) {
                return callback(e);
            }
            // if result is Promise object
            if (_isObject(result) && typeof result.then === "function") {
                result.then(function(value) {
                    callback(null, value);
                })["catch"](function(err) {
                    callback(err.message ? err : new Error(err));
                });
            } else {
                callback(null, result);
            }
        });
    };
  • 官方示例:
// passing a regular synchronous function
async.waterfall([
    async.apply(fs.readFile, filename, "utf8"),
    async.asyncify(JSON.parse),
    function (data, next) {
        // data is the result of parsing the text.
        // If there was a parsing error, it would have been caught.
    }
], callback);

// passing a function returning a promise
async.waterfall([
    async.apply(fs.readFile, filename, "utf8"),
    async.asyncify(function (contents) {
        return db.model.create(contents);
    }),
    function (model, next) {
        // `model` is the instantiated model object.
        // If there was an error, this function would be skipped.
    }
], callback);

// es6 example
var q = async.queue(async.asyncify(async function(file) {
    var intermediateStep = await processFile(file);
    return await somePromise(intermediateStep)
}));

q.push(files);

 

整体代码

/*!
 * async
 * https://github.com/caolan/async
 *
 * Copyright 2010-2014 Caolan McMahon
 * Released under the MIT license
 */
(function () {

    var async = {};
    function noop() {}
    function identity(v) {
        return v;
    }
    function toBool(v) {
        return !!v;
    }
    function notId(v) {
        return !v;
    }

    // global on the server, window in the browser
    var previous_async;

    // Establish the root object, `window` (`self`) in the browser, `global`
    // on the server, or `this` in some virtual machines. We use `self`
    // instead of `window` for `WebWorker` support.
    var root = typeof self === 'object' && self.self === self && self ||
            typeof global === 'object' && global.global === global && global ||
            this;

    if (root != null) {
        previous_async = root.async;
    }

    async.noConflict = function () {
        root.async = previous_async;
        return async;
    };

    // 包装执行函数,执行完成后清空
    function only_once(fn) {
        return function() {
            if (fn === null) throw new Error("Callback was already called.");
            fn.apply(this, arguments);
            fn = null;
        };
    }

    // 包装执行函数,执行完成后清空
    function _once(fn) {
        return function() {
            if (fn === null) return;
            fn.apply(this, arguments);
            fn = null;
        };
    }

    //// cross-browser compatiblity functions ////

    // 转化为字符串
    var _toString = Object.prototype.toString;

    // 是否数组
    var _isArray = Array.isArray || function (obj) {
        return _toString.call(obj) === '[object Array]';
    };

    // 是否对象
    var _isObject = function(obj) {
        var type = typeof obj;
        return type === 'function' || type === 'object' && !!obj;
    };

    // 是否数组或伪数组
    function _isArrayLike(arr) {
        return _isArray(arr) || (
            // has a positive integer length property
            typeof arr.length === "number" &&
            arr.length >= 0 &&
            arr.length % 1 === 0
        );
    }

    // 遍历数组执行回调
    function _arrayEach(arr, iterator) {
        var index = -1,
            length = arr.length;

        while (++index < length) {
            iterator(arr[index], index, arr);
        }
    }

    // 由回调函数重置数组的元素项
    function _map(arr, iterator) {
        var index = -1,
            length = arr.length,
            result = Array(length);

        while (++index < length) {
            result[index] = iterator(arr[index], index, arr);
        }
        return result;
    }

    // 由0到count构成数组
    function _range(count) {
        return _map(Array(count), function (v, i) { return i; });
    }

    // 遍历数组项用回调对memo作处理
    function _reduce(arr, iterator, memo) {
        _arrayEach(arr, function (x, i, a) {
            memo = iterator(memo, x, i, a);
        });
        return memo;
    }

    // 遍历对象的属性执行回调
    function _forEachOf(object, iterator) {
        _arrayEach(_keys(object), function (key) {
            iterator(object[key], key);
        });
    }

    // 获取元素的index,不存在是返回-1
    function _indexOf(arr, item) {
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] === item) return i;
        }
        return -1;
    }

    // 获取对象的属性
    var _keys = Object.keys || function (obj) {
        var keys = [];
        for (var k in obj) {
            if (obj.hasOwnProperty(k)) {
                keys.push(k);
            }
        }
        return keys;
    };

    // 返回以数组元素项序号或对象主键作为返回值的函数,每执行一次通过闭包i+1,构成遍历
    function _keyIterator(coll) {
        var i = -1;
        var len;
        var keys;
        if (_isArrayLike(coll)) {
            len = coll.length;
            return function next() {
                i++;
                return i < len ? i : null;
            };
        } else {
            keys = _keys(coll);
            len = keys.length;
            return function next() {
                i++;
                return i < len ? keys[i] : null;
            };
        }
    }

    // 约定从返回函数的第几项开始获取参数,0、1有效,返回函数末参为index值
    // startIndex为0时,func传参为返回函数的arguments,默认为0
    // startIndex为1时,func传参为返回函数的arguments[0]、其余项
    function _restParam(func, startIndex) {
        startIndex = startIndex == null ? func.length - 1 : +startIndex;
        return function() {
            var length = Math.max(arguments.length - startIndex, 0);
            var rest = Array(length);
            for (var index = 0; index < length; index++) {
                rest[index] = arguments[index + startIndex];
            }
            switch (startIndex) {
                case 0: return func.call(this, rest);
                case 1: return func.call(this, arguments[0], rest);
            }
            // Currently unused but handle cases outside of the switch statement:
            // var args = Array(startIndex + 1);
            // for (index = 0; index < startIndex; index++) {
            //     args[index] = arguments[index];
            // }
            // args[startIndex] = rest;
            // return func.apply(this, args);
        };
    }

    // 没有index的数组项处理函数
    function _withoutIndex(iterator) {
        return function (value, index, callback) {
            return iterator(value, callback);
        };
    }

    //// exported async module functions ////

    //// nextTick implementation with browser-compatible fallback ////

    // capture the global reference to guard against fakeTimer mocks
    var _setImmediate = typeof setImmediate === 'function' && setImmediate;

    var _delay = _setImmediate ? function(fn) {
        // not a direct alias for IE10 compatibility
        _setImmediate(fn);
    } : function(fn) {
        setTimeout(fn, 0);
    };

    if (typeof process === 'object' && typeof process.nextTick === 'function') {
        async.nextTick = process.nextTick;
    } else {
        async.nextTick = _delay;
    }

    // 浏览器使用setTimeout、服务器端使用process.nextTick,在setImmediate函数不存在的前提下
    async.setImmediate = _setImmediate ? _delay : async.nextTick;

    // 实现功能同async.eachOf,只是iterator函数中没有数组的index值,或者没有对象属性集合的index值
    async.forEach =
    async.each = function (arr, iterator, callback) {
        return async.eachOf(arr, _withoutIndex(iterator), callback);
    };

    // 实现功能同async.eachOfSeries,只是iterator函数中没有数组的index值,或者没有对象属性集合的index值
    async.forEachSeries =
    async.eachSeries = function (arr, iterator, callback) {
        return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
    };

    // 实现功能同async.eachOfLimit,只是iterator函数中没有数组的index值,或者没有对象属性集合的index值
    async.forEachLimit =
    async.eachLimit = function (arr, limit, iterator, callback) {
        return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
    };

    // 遍历object对象执行iterator,报错或遍历完成后调用callback(error)
    // callback(error)函数的触发时机需要手动在iterator中设置
    /*官方示例
    var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
    var configs = {};

    async.forEachOf(obj, function (value, key, callback) {
        fs.readFile(__dirname + value, "utf8", function (err, data) {
            if (err) return callback(err);
            try {
                configs[key] = JSON.parse(data);
            } catch (e) {
                return callback(e);
            }
            callback();
        });
    }, function (err) {
        if (err) console.error(err.message);
        // configs is now a map of JSON data
        doSomethingWith(configs);
    });*/
    async.forEachOf =
    async.eachOf = function (object, iterator, callback) {
        callback = _once(callback || noop);
        object = object || [];

        var iter = _keyIterator(object);
        var key, completed = 0;

        while ((key = iter()) != null) {// 反复执行闭包函数iter遍历对象
            completed += 1;
            // only_once(done)中调用外部函数callback,机理同Promise-resolve相似
            iterator(object[key], key, only_once(done));
        }

        if (completed === 0) callback(null);

        function done(err) {
            completed--;
            if (err) {
                callback(err);
            }
            // Check key is null in case iterator isn't exhausted
            // and done resolved synchronously.
            else if (key === null && completed <= 0) {
                callback(null);
            }
        }
    };

    // 本次iterator延迟执行完毕后,通过回调函数only_once(done)触发下一个iterator执行
    // _keyIterator函数的意义遍历的节奏变得可控,可终止,可触发,通常的each方法则不能
    async.forEachOfSeries =
    async.eachOfSeries = function (obj, iterator, callback) {
        callback = _once(callback || noop);
        obj = obj || [];
        var nextKey = _keyIterator(obj);
        var key = nextKey();
        function iterate() {
            var sync = true;
            if (key === null) {
                return callback(null);
            }
            iterator(obj[key], key, only_once(function (err) {
                if (err) {
                    callback(err);
                }
                else {
                    key = nextKey();
                    if (key === null) {
                        return callback(null);
                    } else {
                        if (sync) {
                            async.setImmediate(iterate);
                        } else {
                            iterate();
                        }
                    }
                }
            }));
            sync = false;
        }
        iterate();
    };


    // iterator同时执行个数限制为limit,延迟完成后加载下一个
    // limit=1时,eachOfLimit方法同async.eachOfSeries
    // limit=数组长度或对象属性集合的长度时,eachOfLimit方法同async.eachOf
    async.forEachOfLimit =
    async.eachOfLimit = function (obj, limit, iterator, callback) {
        _eachOfLimit(limit)(obj, iterator, callback);
    };

    function _eachOfLimit(limit) {

        return function (obj, iterator, callback) {
            callback = _once(callback || noop);
            obj = obj || [];
            var nextKey = _keyIterator(obj);
            if (limit <= 0) {
                return callback(null);
            }
            var done = false;
            var running = 0;// 记录iterator执行个数,iterator启动前+1,执行完成后-1
            var errored = false;

            (function replenish () {
                if (done && running <= 0) {
                    return callback(null);
                }

                while (running < limit && !errored) {
                    var key = nextKey();
                    if (key === null) {
                        done = true;
                        if (running <= 0) {
                            callback(null);
                        }
                        return;
                    }
                    running += 1;
                    iterator(obj[key], key, only_once(function (err) {
                        running -= 1;
                        if (err) {
                            callback(err);
                            errored = true;
                        }
                        else {
                            replenish();
                        }
                    }));
                }
            })();
        };
    }

    function doParallel(fn) {
        return function (obj, iterator, callback) {
            return fn(async.eachOf, obj, iterator, callback);
        };
    }
    function doParallelLimit(fn) {
        return function (obj, limit, iterator, callback) {
            return fn(_eachOfLimit(limit), obj, iterator, callback);
        };
    }
    function doSeries(fn) {
        return function (obj, iterator, callback) {
            return fn(async.eachOfSeries, obj, iterator, callback);
        };
    }

    function _asyncMap(eachfn, arr, iterator, callback) {
        callback = _once(callback || noop);
        arr = arr || [];
        var results = _isArrayLike(arr) ? [] : {};
        eachfn(arr, function (value, index, callback) {
            iterator(value, function (err, v) {
                results[index] = v;
                callback(err);
            });
        }, function (err) {
            callback(err, results);
        });
    }

    // 使用async.eachOf方法遍历obj执行iterator,主要目的是获取results,传给最终回调函数callback
    async.map = doParallel(_asyncMap);
    async.mapSeries = doSeries(_asyncMap);
    async.mapLimit = doParallelLimit(_asyncMap);

    // 调用eachOfSeries遍历arr,延迟完成后更新memo,最后将memo传给最终的回调函数callback
    async.inject =
    async.foldl =
    async.reduce = function (arr, memo, iterator, callback) {
        async.eachOfSeries(arr, function (x, i, callback) {
            iterator(memo, x, function (err, v) {
                memo = v;// 更新memo
                callback(err);// 错误处理
            });
        }, function (err) {
            callback(err, memo);//memo不是通过传值或者闭包驻留,由上级作用域赋予
        });
    };

    // 自右向左遍历
    async.foldr =
    async.reduceRight = function (arr, memo, iterator, callback) {
        var reversed = _map(arr, identity).reverse();
        async.reduce(reversed, memo, iterator, callback);
    };

    // 同async.reduce,主要功能是延迟后处理memo,再将memo交给callback回调,只是不阻塞延时函数执行
    async.transform = function (arr, memo, iterator, callback) {
        if (arguments.length === 3) {
            callback = iterator;
            iterator = memo;
            memo = _isArray(arr) ? [] : {};
        }

        async.eachOf(arr, function(v, k, cb) {
            iterator(memo, v, k, cb);
        }, function(err) {
            callback(err, memo);
        });
    };

    function _filter(eachfn, arr, iterator, callback) {
        var results = [];
        eachfn(arr, function (x, index, callback) {
            iterator(x, function (v) {
                if (v) {
                    results.push({index: index, value: x});
                }
                callback();
            });
        }, function () {
            callback(_map(results.sort(function (a, b) { // 由回调函数重置数组的元素项为results的value键值
                return a.index - b.index;
            }), function (x) {
                return x.value;
            }));
        });
    }

    // 调用async.eachOf方法遍历obj执行iterator,通过iterator的回调传参v过滤,返回数组results
    // 经过处理后,构成按序排列原元素值的数组,最终传给callback回调
    async.select =
    async.filter = doParallel(_filter);

    async.selectLimit =
    async.filterLimit = doParallelLimit(_filter);

    async.selectSeries =
    async.filterSeries = doSeries(_filter);

    function _reject(eachfn, arr, iterator, callback) {
        _filter(eachfn, arr, function(value, cb) {// cb在_filter函数中写就,cb为引用
            iterator(value, function(v) {
                cb(!v);
            });
        }, callback);
    }

    // 与async.filter的不同是,reject方法的过滤条件是,iterator的回调传参v为否值
    async.reject = doParallel(_reject);
    async.rejectLimit = doParallelLimit(_reject);
    async.rejectSeries = doSeries(_reject);

    // 以async.some方法解读
    // check、getResult均为传递函数,一个转化为布尔值,一个原样输出
    function _createTester(eachfn, check, getResult) {
        return function(arr, limit, iterator, cb) {
            function done() {
                if (cb) cb(getResult(false, void 0));
            }
            function iteratee(x, _, callback) {
                if (!cb) return callback();
                // 参数function(v){}由内部函数传给外部,作为iterator的回调,执行done回调
                iterator(x, function (v) {// v由外部函数传入,x是arr的元素项
                    if (cb && check(v)) {
                        // v为真、cb存在时执行cb回调,cb和iterator都赋值为false
                        // 因为iteratee中首先判断cb是否为否值,后续遍历直接进入callback回调
                        // 进入callback回调,callback在遍历执行完成时才有意义
                        cb(getResult(true, x));
                        cb = iterator = false;
                    }
                    callback();
                });
            }
            if (arguments.length > 3) {
                eachfn(arr, limit, iteratee, done);
            } else {
                cb = iterator;
                iterator = limit;
                eachfn(arr, iteratee, done);
            }
        };
    }

    // 调用async.eachOf方法,arr参数中有一项满足条件时,回调获得结果为真
    // 回调时机为遍历的每个阶段执行完毕
    async.any =
    async.some = _createTester(async.eachOf, toBool, identity);

    async.someLimit = _createTester(async.eachOfLimit, toBool, identity);

    // 调用async.eachOf方法,arr参数中每一项满足条件时,回调获得结果为真
    // 回调时机为遍历执行完成时
    async.all =
    async.every = _createTester(async.eachOf, notId, notId);

    async.everyLimit = _createTester(async.eachOfLimit, notId, notId);

    function _findGetResult(v, x) {
        return x;
    }
    // 与some方法相同,调用了_createTester函数,差别是some传参为v判断条件,detect传参为arr的元素项
    async.detect = _createTester(async.eachOf, identity, _findGetResult);
    async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);
    async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);

    // 根据用户设置的criteria排序
    async.sortBy = function (arr, iterator, callback) {
        async.map(arr, function (x, callback) {
            iterator(x, function (err, criteria) {
                if (err) {
                    callback(err);
                }
                else {
                    callback(null, {value: x, criteria: criteria});
                }
            });
        }, function (err, results) {
            if (err) {
                return callback(err);
            }
            else {
                callback(null, _map(results.sort(comparator), function (x) {
                    return x.value;
                }));
            }

        });

        function comparator(left, right) {
            var a = left.criteria, b = right.criteria;
            return a < b ? -1 : a > b ? 1 : 0;
        }
    };

    /*---------------------------------------------------------------------------------*/


    // 自动以无依赖的函数到依赖执行完成的函数顺序执行函数
    // tasks以函数映射名为键,函数队列为值,尾参是处理results的回调函数
    async.auto = function (tasks, concurrency, callback) {
        if (typeof arguments[1] === 'function') {
            // concurrency is optional, shift the args.
            callback = concurrency;
            concurrency = null;
        }
        callback = _once(callback || noop);
        var keys = _keys(tasks);
        var remainingTasks = keys.length;// tasks对象共有多少键,即共多少任务

        // 没有任务,直接调用回调函数
        if (!remainingTasks) {
            return callback(null);
        }
        if (!concurrency) {
            concurrency = remainingTasks;// concurrency同时执行的任务数,默认为tasks对象有多少键
        }

        var results = {};
        var runningTasks = 0;// 跑的任务数,与concurrency比较以对同时跑的任务数作限制

        var hasError = false;

        // 需要依赖函数完成加载后才执行的函数,通过addListener方法添加到listeners队列
        // 每当一个函数加载完成,调用taskComplete执行依赖加载完成的函数项,调用removeListener更新listeners队列
        var listeners = [];
        function addListener(fn) {
            listeners.unshift(fn);
        }
        function removeListener(fn) {
            var idx = _indexOf(listeners, fn);
            if (idx >= 0) listeners.splice(idx, 1);
        }

        // remainingTasks-1,遍历listeners执行依赖加载完成的函数项
        function taskComplete() {
            remainingTasks--;
            _arrayEach(listeners.slice(0), function (fn) {
                fn();
            });
        }

        // tasks中任务函数已执行完毕的情况下,remainingTasks=0,执行最终回调函数callback
        addListener(function () {
            if (!remainingTasks) {
                callback(null, results);
            }
        });

        _arrayEach(keys, function (k) {
            if (hasError) return;
            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];

            // 因为startIndex为0,_restParam作用是将taskCallback赋值为function(err,args),处理results
            var taskCallback = _restParam(function(err, args) {
                runningTasks--;
                if (args.length <= 1) {
                    args = args[0];
                }
                if (err) {
                    var safeResults = {};
                    _forEachOf(results, function(val, rkey) {
                        safeResults[rkey] = val;
                    });
                    safeResults[k] = args;// 关于k值的驻留???
                    hasError = true;

                    // 报错直接调用最终回调函数
                    callback(err, safeResults);

                // 没有错误,执行taskComplete,遍历listeners执行依赖加载完成的函数项
                }else {
                    results[k] = args;// results由tasks的末尾项task[task.length - 1]参数带入
                    async.setImmediate(taskComplete);
                }
            });

            // 检查依赖的函数是否存在,依赖可以是数组形式,但不能依赖自身
            var requires = task.slice(0, task.length - 1);// 排除最后一项
            // prevent dead-locks
            var len = requires.length;
            var dep;
            while (len--) {
                if (!(dep = tasks[requires[len]])) {
                    throw new Error('Has nonexistent dependency in ' + requires.join(', '));
                }
                if (_isArray(dep) && _indexOf(dep, k) >= 0) {
                    throw new Error('Has cyclic dependencies');
                }
            }

            // 依赖函数x在results中,执行函数k不在results中,且同时跑的函数个数runningTasks小于限制
            function ready() {
                // _reduce遍历数组项对尾参memo作处理,迭代器函数iterator中首参为memo,次参为元素项
                return runningTasks < concurrency && _reduce(requires, function (a, x) {
                    return (a && results.hasOwnProperty(x));
                }, true) && !results.hasOwnProperty(k);
            }

            // task[task.length - 1]末尾项为函数,之前为依赖
            // taskCallback,通过调用taskComplete,遍历listeners执行依赖加载完成的函数项
            if (ready()) {
                runningTasks++;
                task[task.length - 1](taskCallback, results);
            }else {
                addListener(listener);
            }

            // 添加listeners函数队列的依赖函数,执行时runningTasks+1,删除listeners队列依赖
            function listener() {
                if (ready()) {
                    runningTasks++;
                    removeListener(listener);
                    task[task.length - 1](taskCallback, results);
                }
            }
        });
    };

    // 报错时重复尝试task任务函数,直到最末一个task任务或某个task任务执行成功时,跳向最终回调
    async.retry = function(times, task, callback) {
        var DEFAULT_TIMES = 5;
        var DEFAULT_INTERVAL = 0;

        var attempts = [];

        var opts = {
            times: DEFAULT_TIMES,// task执行次数
            interval: DEFAULT_INTERVAL// task执行完成间隙时间
        };

        function parseTimes(acc, t){
            if(typeof t === 'number'){
                acc.times = parseInt(t, 10) || DEFAULT_TIMES;
            } else if(typeof t === 'object'){
                acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;
                acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;
            } else {
                throw new Error('Unsupported argument type for \'times\': ' + typeof t);
            }
        }

        var length = arguments.length;
        if (length < 1 || length > 3) {
            throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');
        } else if (length <= 2 && typeof times === 'function') {
            callback = task;
            task = times;
        }
        if (typeof times !== 'function') {
            parseTimes(opts, times);
        }
        opts.callback = callback;
        opts.task = task;

        function wrappedTask(wrappedCallback, wrappedResults) {
            function retryAttempt(task, finalAttempt) {
                // seriesCallback为task任务执行完成后回调函数,通过async.series方法设置
                // seriesCallback首参等同async.series方法中执行函数的回调函数参数err,正常执行需为否
                // 为真跳到最终回调
                // seriesCallback在async.series方法的意义是调用下一个task或最终回调
                return function(seriesCallback) {
                    // task首参为函数,该函数中调用async.series方法seriesCallback,也就是设置回调时机
                    task(function(err, result){
                        // err为否,执行成功的前提下,跳到最终回调,结束task任务的反复执行
                        // err为真,忽略该错误,继续执行task任务
                        // 到最末一个task任务时,执行完毕即调用最终回调
                        seriesCallback(!err || finalAttempt, {err: err, result: result});
                    }, wrappedResults);
                };
            }

            // 两个task任务之间添加等待时间
            function retryInterval(interval){
                return function(seriesCallback){
                    setTimeout(function(){
                        seriesCallback(null);
                    }, interval);
                };
            }

            while (opts.times) {

                var finalAttempt = !(opts.times-=1);
                attempts.push(retryAttempt(opts.task, finalAttempt));
                // 两个task任务之间添加等待时间
                if(!finalAttempt && opts.interval > 0){
                    attempts.push(retryInterval(opts.interval));
                }
            }

            // function(done,data)作为async.series方法的最终回调,done为是否报错,data为传入数据
            async.series(attempts, function(done, data){
                // data为tasks处理获得的最终值,获取尾项,其余项为中间处理值
                data = data[data.length - 1];
                (wrappedCallback || opts.callback)(data.err, data.result);
            });
        }

        // If a callback is passed, run this as a controll flow
        // 没有callback参数项时,输出为函数,需要传递wrappedCallback与wrappedResults
        return opts.callback ? wrappedTask() : wrappedTask;
    };

    // 顺序执行tasks任务函数,并为任务函数传递参数,报错或任务函数执行完毕调用callback
    async.waterfall = function (tasks, callback) {
        callback = _once(callback || noop);
        if (!_isArray(tasks)) {
            var err = new Error('First argument to waterfall must be an array of functions');
            return callback(err);
        }
        if (!tasks.length) {
            return callback();
        }
        function wrapIterator(iterator) {
            return _restParam(function (err, args) {
                if (err) {
                    callback.apply(null, [err].concat(args));
                }
                else {
                    var next = iterator.next();// async.iterator方法获取下一个执行函数
                    if (next) {
                        args.push(wrapIterator(next));
                    }
                    else {
                        args.push(callback);
                    }
                    // 调用ensureAsync避免堆栈溢出
                    // 执行iterator函数,函数尾参为下一个iterator函数或最终回调callback
                    // 同时为下一个iterator函数或最终回调callback传递参数
                    ensureAsync(iterator).apply(null, args);
                }
            });
        }
        wrapIterator(async.iterator(tasks))();
    };

    function _parallel(eachfn, tasks, callback) {
        callback = callback || noop;
        var results = _isArrayLike(tasks) ? [] : {};

        eachfn(tasks, function (task, key, callback) {
            task(_restParam(function (err, args) {
                if (args.length <= 1) {
                    args = args[0];
                }
                results[key] = args;// 根据tasks数据类型构建results,传给最终回调,results根据作用域传递
                callback(err);
            }));
        }, function (err) {
            callback(err, results);
        });
    }

    // 遍历执行tasks中任务函数,数组或对象形式构建results,传给回调函数callback
    async.parallel = function (tasks, callback) {
        _parallel(async.eachOf, tasks, callback);
    };

    async.parallelLimit = function(tasks, limit, callback) {
        _parallel(_eachOfLimit(limit), tasks, callback);
    };

    async.series = function(tasks, callback) {
        _parallel(async.eachOfSeries, tasks, callback);
    };

    // 以可控的方式遍历执行tasks函数队列
    // makeCallback构建执行函数,并作为返回值
    // 执行函数调用过程中,执行tasks的任务函数,并调用makeCallback函数构建下一个任务函数的执行函数作为返回值
    // 执行函数的next方法获取下一个任务函数的执行函数
    async.iterator = function (tasks) {
        function makeCallback(index) {
            function fn() {// 执行函数
                if (tasks.length) {
                    tasks[index].apply(null, arguments);
                }
                return fn.next();
            }
            fn.next = function () {
                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
            };
            return fn;
        }
        return makeCallback(0);
    };

    // 返回fn的执行函数,目的是重设fn的参数
    async.apply = _restParam(function (fn, args) {
        return _restParam(function (callArgs) {
            return fn.apply(
                null, args.concat(callArgs)
            );
        });
    });

    // 拼接arr元素项传参给回调,前提是没有捕获到错误,捕获到错误则略过
    function _concat(eachfn, arr, fn, callback) {
        var result = [];
        eachfn(arr, function (x, index, cb) {
            fn(x, function (err, y) {
                result = result.concat(y || []);
                cb(err);
            });
        }, function (err) {
            callback(err, result);
        });
    }
    async.concat = doParallel(_concat);
    async.concatSeries = doSeries(_concat);

    // test合格后,执行iterator,否则跳到最终回调callback,目的是处理变量
    async.whilst = function (test, iterator, callback) {
        callback = callback || noop;
        if (test()) {
            var next = _restParam(function(err, args) {// args由外部函数传入
                if (err) {
                    callback(err);
                } else if (test.apply(this, args)) {
                    iterator(next);// 调用下一个iterator
                } else {
                    callback.apply(null, [null].concat(args));// 执行完成后最终回调,参数为null、args
                }
            });
            iterator(next);// 第一个iterator
        } else {
            callback(null);
        }
    };

    // iterator必然执行一次,其他看test检验是否合格
    async.doWhilst = function (iterator, test, callback) {
        var calls = 0;
        return async.whilst(function() {
            return ++calls <= 1 || test.apply(this, arguments);
        }, iterator, callback);
    };

    // 取反校验
    async.until = function (test, iterator, callback) {
        return async.whilst(function() {
            return !test.apply(this, arguments);
        }, iterator, callback);
    };

    async.doUntil = function (iterator, test, callback) {
        return async.doWhilst(iterator, function() {
            return !test.apply(this, arguments);
        }, callback);
    };

    // 同whilst,不同的是whilst方法校验立即执行,during方法校验需要等待使用者向test回调函数中注入参数
    // 可以实现异步校验,test回调参数通过延时函数获得
    async.during = function (test, iterator, callback) {
        callback = callback || noop;

        var next = _restParam(function(err, args) {
            if (err) {
                callback(err);
            } else {
                args.push(check);// args可以在同步处理或异步处理后使用
                test.apply(this, args);// args尾参中传入check,使用者调用执行
            }
        });

        var check = function(err, truth) {
            if (err) {
                callback(err);
            } else if (truth) {
                iterator(next);
            } else {
                callback(null);
            }
        };

        test(check);
    };

    async.doDuring = function (iterator, test, callback) {
        var calls = 0;
        async.during(function(next) {
            if (calls++ < 1) {
                next(null, true);
            } else {
                test.apply(this, arguments);
            }
        }, iterator, callback);
    };

    // 加载或执行任务函数(回调函数),任务函数的目的是启动任务函数中的回调函数
    function _queue(worker, concurrency, payload) {
        if (concurrency == null) {
            concurrency = 1;
        }
        else if(concurrency === 0) {
            throw new Error('Concurrency must not be zero');
        }
        // q.tasks待执行的任务函数队列添加任务
        function _insert(q, data, pos, callback) {// pos头部插入任务队列q.tasks
            if (callback != null && typeof callback !== "function") {
                throw new Error("task callback must be a function");
            }
            q.started = true;
            if (!_isArray(data)) {
                data = [data];
            }
            if(data.length === 0 && q.idle()) {
                // call drain immediately if there are no tasks
                return async.setImmediate(function() {
                    q.drain();
                });
            }
            _arrayEach(data, function(task) {
                var item = {
                    data: task,
                    callback: callback || noop
                };

                if (pos) {
                    q.tasks.unshift(item);
                } else {
                    q.tasks.push(item);
                }

                if (q.tasks.length === q.concurrency) {
                    q.saturated();
                }
            });
            async.setImmediate(q.process);
        }
        // 一个任务执行完成后回调,执行任务数workers-1,更新执行任务队列workersList
        // 执行任务固有的回调函数task.callback,调用执行下一个任务
        function _next(q, tasks) {
            return function(){
                workers -= 1;

                var removed = false;
                var args = arguments;
                // 更新workersList执行任务队列
                _arrayEach(tasks, function (task) {
                    _arrayEach(workersList, function (worker, index) {
                        if (worker === task && !removed) {
                            workersList.splice(index, 1);
                            removed = true;
                        }
                    });

                    // 执行任务固有的回调函数
                    task.callback.apply(task, args);
                });
                if (q.tasks.length + workers === 0) {
                    q.drain();
                }
                q.process();
            };
        }

        var workers = 0;// 执行中的任务数量
        var workersList = [];// 执行中的任务
        var q = {
            tasks: [],// 任务函数队列
            concurrency: concurrency,// 同步执行的worker个数
            payload: payload,
            saturated: noop,// 空函数,改写后实现功能,同步执行达到限制时执行
            empty: noop,// 改写实现功能,任务为空时执行
            drain: noop,// 改写实现功能,所有任务都执行完成后调用
            started: false,
            paused: false,
            push: function (data, callback) {// 尾部插入
                _insert(q, data, false, callback);
            },
            kill: function () {// 清空q.tasks任务函数队列
                q.drain = noop;
                q.tasks = [];
            },
            unshift: function (data, callback) {// 头部插入
                _insert(q, data, true, callback);
            },
            process: function () {
                while(!q.paused && workers < q.concurrency && q.tasks.length){

                    // 从q.tasks中取出任务,并更新q.tasks需要执行的任务函数队列
                    // tasks一个任务单元,任务单元中的任务同步执行
                    var tasks = q.payload ?
                        q.tasks.splice(0, q.payload) :
                        q.tasks.splice(0, q.tasks.length);// 预加载的任务函数数量

                    var data = _map(tasks, function (task) {
                        return task.data;
                    });

                    if (q.tasks.length === 0) {
                        q.empty();
                    }
                    workers += 1;
                    workersList.push(tasks[0]);
                    var cb = only_once(_next(q, tasks));
                    worker(data, cb);// _queue函数参数worker执行过程中调用cb函数执行下一个任务函数
                }
            },
            length: function () {// 需要执行的任务
                return q.tasks.length;
            },
            running: function () {// 同步执行的任务数
                return workers;
            },
            workersList: function () {// 同步执行的任务
                return workersList;
            },
            idle: function() {// 所有任务都已执行完成
                return q.tasks.length + workers === 0;
            },
            pause: function () {// 中断process函数执行
                q.paused = true;
            },
            resume: function () {// 恢复执行
                if (q.paused === false) { return; }
                q.paused = false;
                var resumeCount = Math.min(q.concurrency, q.tasks.length);
                // Need to call q.process once per concurrent
                // worker to preserve full concurrency after pause
                for (var w = 1; w <= resumeCount; w++) {
                    async.setImmediate(q.process);
                }
            }
        };
        return q;
    }

    // 返回queue对象,听过该对象添加或执行任务函数,通过调用worker函数执行任务函数
    // concurrency限制同步执行的任务个数
    async.queue = function (worker, concurrency) {
        // push进queue对象的任务函数通过调用worker执行其功能
        var q = _queue(function (items, cb) {
            worker(items[0], cb);
        }, concurrency, 1);

        return q;
    };

    // 内部调用async.queue方法返回queue对象,只是删除了unshift方法、改写了push方法
    // 设置任务函数执行的优先级
    async.priorityQueue = function (worker, concurrency) {

        // 比较优先级,越低越高优先级
        function _compareTasks(a, b){
            return a.priority - b.priority;
        }

        // 通过不断和拆分数组的中值作比较,得出item应该插到sequence数组中哪个位置
        function _binarySearch(sequence, item, compare) {
            var beg = -1,
                end = sequence.length - 1;
            while (beg < end) {
                var mid = beg + ((end - beg + 1) >>> 1);// 无符号右移,即除2,忽略余数
                if (compare(item, sequence[mid]) >= 0) {
                    beg = mid;
                } else {
                    end = mid - 1;
                }
            }
            return beg;
        }

        function _insert(q, data, priority, callback) {
            if (callback != null && typeof callback !== "function") {
                throw new Error("task callback must be a function");
            }
            q.started = true;
            if (!_isArray(data)) {
                data = [data];
            }
            if(data.length === 0) {
                // call drain immediately if there are no tasks
                return async.setImmediate(function() {
                    q.drain();
                });
            }
            _arrayEach(data, function(task) {
                var item = {
                    data: task,
                    priority: priority,
                    callback: typeof callback === 'function' ? callback : noop
                };

                q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);

                if (q.tasks.length === q.concurrency) {
                    q.saturated();
                }
                async.setImmediate(q.process);
            });
        }

        // Start with a normal queue
        var q = async.queue(worker, concurrency);

        // Override push to accept second parameter representing priority
        q.push = function (data, priority, callback) {
            _insert(q, data, priority, callback);
        };

        // Remove unshift function
        delete q.unshift;

        return q;
    };

    // 返回queue对象,听过该对象添加或执行任务函数,通过调用worker函数执行任务函数
    // payload单次执行的任务单元中包含几条任务函数,这几条任务函数和下一个任务单元同步执行
    async.cargo = function (worker, payload) {
        return _queue(worker, 1, payload);
    };

    function _console_fn(name) {
        return _restParam(function (fn, args) {
            // 通过内部函数向外部函数传递回调函数function(err,args)作为参数
            // 外部函数中设置回调函数的执行时机
            // 实际意义似乎和在异步函数中直接调用console.log()没差别
            fn.apply(null, args.concat([_restParam(function (err, args) {
                if (typeof console === 'object') {
                    if (err) {
                        if (console.error) {
                            console.error(err);
                        }
                    }
                    else if (console[name]) {
                        _arrayEach(args, function (x) {
                            console[name](x);
                        });
                    }
                }
            })]));
        });
    }
    async.log = _console_fn('log');
    async.dir = _console_fn('dir');// 显示dom试图
    /*async.info = _console_fn('info');
    async.warn = _console_fn('warn');
    async.error = _console_fn('error');*/

    // 传参相同,fn已执行的状态下,重复调用回调函数,或fn执行中,添加回调函数
    async.memoize = function (fn, hasher) {
        var memo = {};
        var queues = {};
        var has = Object.prototype.hasOwnProperty;
        hasher = hasher || identity;
        var memoized = _restParam(function memoized(args) {
            var callback = args.pop();
            var key = hasher.apply(null, args);
            if (has.call(memo, key)) {   
                // 已执行,立即执行fn的回调
                async.setImmediate(function () {
                    callback.apply(null, memo[key]);
                });
            }
            else if (has.call(queues, key)) {
                // fn执行过程中,参数args相同,添加回调callback
                queues[key].push(callback);
            }
            else {
                queues[key] = [callback];// 执行前fn回调添加到queues队列
                fn.apply(null, args.concat([_restParam(function (args) {
                    memo[key] = args;// fn执行完成更新memo记录已执行,对象的键可以是数组、对象等数据类型
                    var q = queues[key];
                    delete queues[key];// 执行完清空该fn回调队列queues[key]
                    for (var i = 0, l = q.length; i < l; i++) {
                        q[i].apply(null, args);// 执行fn的回调
                    }
                })]));
            }
        });
        memoized.memo = memo;
        memoized.unmemoized = fn;// 没有memo记录的直接调用
        return memoized;
    };

    // 对async.memoize返回对象或普通函数fn作处理,视为普通函数处理
    async.unmemoize = function (fn) {
        return function () {
            return (fn.unmemoized || fn).apply(null, arguments);
        };
    };

    function _times(mapper) {
        return function (count, iterator, callback) {
            // _range(count)输出为0到count构成数组
            mapper(_range(count), iterator, callback);
        };
    }

    // 设置iterator的调用次数count
    async.times = _times(async.map);
    async.timesSeries = _times(async.mapSeries);
    async.timesLimit = function (count, limit, iterator, callback) {
        return async.mapLimit(_range(count), limit, iterator, callback);
    };

    // async.reduce的简化方案,遍历执行函数,对传递数据作处理后传给各回调
    async.seq = function (/* functions... */) {
        var fns = arguments;
        return _restParam(function (args) {
            var that = this;

            var callback = args[args.length - 1];
            if (typeof callback == 'function') {
                args.pop();
            } else {
                callback = noop;
            }

            async.reduce(fns, args, function (newargs, fn, cb) {
                fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {
                    cb(err, nextargs);
                })]));
            },
            function (err, results) {
                callback.apply(that, [err].concat(results));
            });
        });
    };

    async.compose = function (/* functions... */) {
        return async.seq.apply(null, Array.prototype.reverse.call(arguments));
    };

    function _applyEach(eachfn) {
        return _restParam(function(fns, args) {
            var go = _restParam(function(args) {
                var that = this;
                var callback = args.pop();// 尾项为回调函数
                return eachfn(fns, function (fn, _, cb) {
                    fn.apply(that, args.concat([cb]));
                },
                callback);
            });
            if (args.length) {
                return go.apply(this, args);
            }
            else {
                return go;
            }
        });
    }

    // 调用async.eachOf遍历执行fns函数,fns函数参数均相同,且为args、callback
    async.applyEach = _applyEach(async.eachOf);
    async.applyEachSeries = _applyEach(async.eachOfSeries);

    // fn执行完毕,使用next函数,或者调用自身,或者报错时执行回调
    async.forever = function (fn, callback) {
        var done = only_once(callback || noop);
        var task = ensureAsync(fn);
        function next(err) {
            if (err) {
                return done(err);
            }
            task(next);
        }
        next();
    };

    function ensureAsync(fn) {
        // 输入参数最后一项是回调函数,sync为真同步执行状态,为否异步执行状态
        // 改写回调项,async.setImmediate跟普通调用callback的区别是没有堆栈溢出?
        return _restParam(function (args) {
            var callback = args.pop();
            args.push(function () {
                var innerArgs = arguments;
                if (sync) {
                    async.setImmediate(function () {
                        callback.apply(null, innerArgs);
                    });
                } else {
                    callback.apply(null, innerArgs);
                }
            });
            var sync = true;
            fn.apply(this, args);
            sync = false;
        });
    }

    // 改写参数函数fn中参数的回调函数callback设置,callback启动时机依然需使用者触发
    // 改写callback的目的避免同步函数的内存浪费
    async.ensureAsync = ensureAsync;

    // 重设callback首参err为null
    async.constant = _restParam(function(values) {
        var args = [null].concat(values);
        return function (callback) {
            return callback.apply(this, args);
        };
    });

    // 执行func,若返回值为thenable对象,再次执行该thenable对象的then方法,若不是,直接调用回调函数
    async.wrapSync =
    async.asyncify = function asyncify(func) {
        return _restParam(function (args) {
            var callback = args.pop();
            var result;
            try {
                result = func.apply(this, args);
            } catch (e) {
                return callback(e);
            }
            // if result is Promise object
            if (_isObject(result) && typeof result.then === "function") {
                result.then(function(value) {
                    callback(null, value);
                })["catch"](function(err) {
                    callback(err.message ? err : new Error(err));
                });
            } else {
                callback(null, result);
            }
        });
    };

    // Node.js
    if (typeof module === 'object' && module.exports) {
        module.exports = async;
    }
    // AMD / RequireJS
    else if (typeof define === 'function' && define.amd) {
        define([], function () {
            return async;
        });
    }
    // included directly via <script> tag
    else {
        root.async = async;
    }

}());

猜你喜欢

转载自schifred.iteye.com/blog/2318936