Article directory
- basic method
- asynchronous traversal
-
- reduce
- reduceRight
- compose
Basic method
Asynchronous traversal
reduce
basic use
- The next iterator will be executed when the parameter is passed to the next one through done
var collection = [1, 3, 2, 4]; var iterator = function(result, num, done) {<!-- --> setTimeout(function() {<!-- --> done(null, result + num); }, num * 10); }; async.reduce(collection, 5, iterator, function(err, res) {<!-- --> console. log(res); // 15 });
accomplish
function reduce(collection, result, iterator, callback) {<!-- --> callback = onlyOnce(callback || noop); var size, key, keys, iter, item, iterate; var sync = false; var completed = 0; if (isArray(collection)) {<!-- --> size = collection. length; iterate = iterator. length === 4 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) {<!-- --> } else if (iteratorSymbol & amp; & amp; collection[iteratorSymbol]) {<!-- --> size = Infinity; iter = collection[iteratorSymbol](); iterate = iterator. length === 4 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) {<!-- --> keys = nativeKeys(collection); size = keys. length; iterate = iterator. length === 4 ? objectIteratorWithKey : objectIterator; } if (!size) {<!-- --> return callback(null, result); } iterate(result); function arrayIterator(result) {<!-- --> iterator(result, collection[completed], done); } function arrayIteratorWithIndex(result) {<!-- --> // results value key next iterator(result, collection[completed], completed, done); } function symbolIterator(result) {<!-- --> item = iter. next(); item.done ? callback(null, result) : iterator(result, item.value, done); } function symbolIteratorWithKey(result) {<!-- --> item = iter. next(); item.done ? callback(null, result) : iterator(result, item.value, completed, done); } function objectIterator(result) {<!-- --> iterator(result, collection[keys[completed]], done); } function objectIteratorWithKey(result) {<!-- --> key = keys[completed]; iterator(result, collection[key], key, done); } function done(err, result) {<!-- --> // pass result through done if (err) {<!-- --> callback(err, result); } else if ( + + completed === size) {<!-- --> iterator = throwError; callback(null, result); } else if (sync) {<!-- --> // Avoid a large number of synchronous tasks blocking the time loop, so it becomes an asynchronous task nextTick(function() {<!-- --> iterate(result); }); } else {<!-- --> sync = true; iterate(result); } sync = false; } }
reduceRight
- reduceRight, traverse from the last digit of the collection
function reduceRight(collection, result, iterator, callback) {<!-- --> callback = onlyOnce(callback || noop); var resIndex, index, key, keys, iter, item, col, iterate; var sync = false; if (isArray(collection)) {<!-- --> resIndex = collection.length; //Start from the last digit of the array iterate = iterator. length === 4 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) {<!-- --> } else if (iteratorSymbol & amp; & amp; collection[iteratorSymbol]) {<!-- --> // For the symbol type, first find all the values, and then reverse the order according to the index col = []; iter = collection[iteratorSymbol](); index = -1; while ((item = iter.next()).done === false) {<!-- --> col[ + + index] = item. value; } collection = col; resIndex = col. length; iterate = iterator. length === 4 ? arrayIteratorWithIndex : arrayIterator; } else if (typeof collection === obj) {<!-- --> keys = nativeKeys(collection); resIndex = keys. length; iterate = iterator. length === 4 ? objectIteratorWithKey : objectIterator; } if (!resIndex) {<!-- --> return callback(null, result); } iterate(result); function arrayIterator(result) {<!-- --> iterator(result, collection[--resIndex], done); } function arrayIteratorWithIndex(result) {<!-- --> iterator(result, collection[--resIndex], resIndex, done); } function objectIterator(result) {<!-- --> iterator(result, collection[keys[--resIndex]], done); } function objectIteratorWithKey(result) {<!-- --> key = keys[--resIndex]; iterator(result, collection[key], key, done); } function done(err, result) {<!-- --> if (err) {<!-- --> callback(err, result); } else if (resIndex === 0) {<!-- --> iterate = throwError; callback(null, result); } else if (sync) {<!-- --> nextTick(function() {<!-- --> iterate(result); }); } else {<!-- --> sync = true; iterate(result); } sync = false; } }
compose
- The difference from ordinary reduce is: the method passed into the iterator needs to be executed and the result passed
basic use
function add1(n, callback) {<!-- --> setTimeout(function () {<!-- --> callback(null, n + 1); }, 10); } function mul3(n, callback) {<!-- --> setTimeout(function () {<!-- --> callback(null, n * 3); }, 10); } var add1mul3 = nac.compose(mul3, add1); //mul3(add1(4)) add1mul3(4, function (err, result) {<!-- --> // result now equals 15 console.log(result) // 15 });
accomplish:
function compose() {<!-- --> // parameter flipped return seq.apply(null, reverse(arguments)); } /** * @memberof async * @namespace seq */ function seq(/* functions... */) {<!-- --> //fns:[add1,mul3] var fns = createArray(arguments); return function() {<!-- --> var self = this // args: [4, callback] var args = createArray(arguments); var callback = args[args. length - 1]; if (typeof callback === func) {<!-- --> args. pop(); } else {<!-- --> callback = noop; } reduce(fns, args, iterator, done); function iterator(newargs, fn, callback) {<!-- --> // The callback here is done in reduce, which will call the next task or the final callback // First time: newargs:[4], fn:add1 // Second time: newargs:[5], fn:mul3 var func = function(err) {<!-- --> //callback called in the task // first time: nextargs:4 + 1=5 // Second time: nextargs:5*3=15 var nextargs = slice(arguments, 1);// Merge the parameters to be passed to the next task into one, which is why the callback is not passed directly callback(err, nextargs); }; // first time: newargs:[4,func] // Second time: newargs:[5,func] newargs.push(func); //The function of push is to pass in the callback // first time: add1(4,func) // second time: mul3(5,func) fn.apply(self, newargs); } function done(err, res) {<!-- --> // [15] res = isArray(res) ? res : [res]; res. unshift(err); callback.apply(self, res); } }; }