UNPKG

insync

Version:

Higher-order functions and common patterns for asynchronous code. Node specific port of async.

611 lines (437 loc) 13.6 kB
'use strict'; // Load modules var Util = require('./util'); // Declare internals var internals = {}; internals.doParallelLimit = function (limit, fn) { return function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return fn.apply(null, [internals._eachLimit(limit)].concat(args)); }; }; internals._map = function (arr) { var result = []; for (var i = 0, il = arr.length; i < il; ++i) { result.push({ index: i, value: arr[i] }); } return result; }; internals._unmap = function (arr) { var result = []; for (var i = 0, il = arr.length; i < il; ++i) { result.push(arr[i].value); } return result; }; internals._asyncMap = function (eachfn, arr, iterator, callback) { arr = internals._map(arr); if (typeof callback !== 'function') { eachfn(arr, function (item, callback) { iterator(item.value, function (err) { callback(err); }); }); } else { (function () { var results = []; eachfn(arr, function (item, callback) { iterator(item.value, function (err, value) { results[item.index] = value; callback(err); }); }, function (err) { callback(err, results); }); })(); } }; internals._filter = function (eachfn, arr, iterator, callback) { var results = []; arr = internals._map(arr); eachfn(arr, function (item, callback) { iterator(item.value, function (err, value) { if (err) { return callback(err); } else if (value) { results.push(item); } callback(); }); }, function (err) { if (err) { return callback(err); } results.sort(function (a, b) { return a.index - b.index; }); results = internals._unmap(results); callback(null, results); }); }; internals._reject = function (eachfn, arr, iterator, callback) { var results = []; arr = internals._map(arr); eachfn(arr, function (item, callback) { iterator(item.value, function (err, value) { if (err) { return callback(err); } else if (!value) { results.push(item); } callback(); }); }, function (err) { if (err) { return callback(err); } results.sort(function (a, b) { return a.index - b.index; }); results = internals._unmap(results); callback(null, results); }); }; internals._detect = function (eachfn, arr, iterator, callback) { eachfn(arr, function (item, cb) { iterator(item, function (err, result) { if (err) { callback(err); callback = Util.noop; } else if (result) { callback(null, item); callback = Util.noop; } else { cb(); } }); }, callback); }; internals._concat = function (eachfn, arr, fn, callback) { var r = []; eachfn(arr, function (x, cb) { fn(x, function (err, y) { r = r.concat(y || []); cb(err); }); }, function (err) { callback(err, r); }); }; // Used in flow.js module.exports.doSeries = internals.doSeries = function (fn) { return function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return fn.apply(null, [module.exports.eachSeries].concat(args)); }; }; // Used in flow.js module.exports.doParallel = internals.doParallel = function (fn) { return function () { for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } return fn.apply(null, [module.exports.each].concat(args)); }; }; // Used in flow.js module.exports._eachLimit = internals._eachLimit = function (limit) { return function (arr, iterator, callback) { callback = callback || Util.noop; if (!arr.length || limit <= 0) { return callback(); } var completed = 0; var started = 0; var running = 0; var errored = false; (function replenish() { var iteratorCallback = function iteratorCallback(err) { if (err) { callback(err); callback = Util.noop; errored = true; } else { completed++; running--; if (completed >= arr.length) { callback(); } else { replenish(); } } }; while (running < limit && started < arr.length && errored === false) { started++; running++; iterator(arr[started - 1], iteratorCallback); } })(); }; }; internals._eachOfLimit = function (limit) { return function (object, iterator, callback) { callback = callback || Util.noop; var isArrayLike = Util.isArrayLike(object); var size = undefined; var keys = undefined; if (isArrayLike) { size = object.length; } else { keys = Object.keys(object); size = keys.length; } if (!size || limit <= 0) { return callback(); } var completed = 0; var started = 0; var running = 0; var errored = false; (function replenish() { var iteratorCallback = function iteratorCallback(err) { if (err) { callback(err); callback = Util.noop; errored = true; } else { completed++; running--; if (completed >= size) { callback(); } else { replenish(); } } }; while (running < limit && started < size && errored === false) { var key = isArrayLike ? started : keys[started]; started++; running++; iterator(object[key], key, iteratorCallback); } })(); }; }; // Used in flow.js module.exports._mapLimit = internals._mapLimit = function (limit) { return internals.doParallelLimit(limit, internals._asyncMap); }; module.exports.each = function (arr, iterator, callback) { callback = callback || Util.noop; if (!arr.length) { return callback(); } var completed = 0; var done = function done(err) { if (err) { callback(err); callback = Util.noop; } else { ++completed; if (completed >= arr.length) { callback(); } } }; for (var i = 0, il = arr.length; i < il; ++i) { iterator(arr[i], Util.onlyOnce(done)); } }; module.exports.eachSeries = function (arr, iterator, callback) { callback = callback || Util.noop; if (!arr.length) { return callback(); } var completed = 0; var iterate = function iterate() { iterator(arr[completed], function (err) { if (err) { callback(err); callback = Util.noop; } else { completed++; if (completed >= arr.length) { callback(); } else { iterate(); } } }); }; iterate(); }; module.exports.eachLimit = function (arr, limit, iterator, callback) { var fn = internals._eachLimit(limit); fn.apply(null, [arr, iterator, callback]); }; module.exports.eachOf = function (object, iterator, callback) { var isArrayLike = Util.isArrayLike(object); var size = undefined; var keys = undefined; if (isArrayLike) { size = object.length; } else { keys = Object.keys(object); size = keys.length; } callback = callback || Util.noop; if (!size) { return callback(); } var completed = 0; var done = function done(err) { if (err) { callback(err); callback = Util.noop; } else { ++completed; if (completed >= size) { callback(); } } }; if (isArrayLike) { for (var i = 0; i < size; ++i) { iterator(object[i], i, Util.onlyOnce(done)); } } else { for (var i = 0; i < size; ++i) { var key = keys[i]; iterator(object[key], key, Util.onlyOnce(done)); } } }; module.exports.eachOfSeries = function (object, iterator, callback) { var isArrayLike = Util.isArrayLike(object); var size = undefined; var keys = undefined; if (isArrayLike) { size = object.length; } else { keys = Object.keys(object); size = keys.length; } callback = callback || Util.noop; if (!size) { return callback(); } var completed = 0; var complete = function complete(err) { if (err) { callback(err); callback = Util.noop; } else { completed++; if (completed >= size) { callback(); } else { iterate(); } } }; var iterate = isArrayLike ? function () { iterator(object[completed], completed, complete); } : function () { var key = keys[completed];iterator(object[key], key, complete); }; iterate(); }; module.exports.eachOfLimit = function (arr, limit, iterator, callback) { var fn = internals._eachOfLimit(limit); fn.apply(null, [arr, iterator, callback]); }; module.exports.map = internals.doParallel(internals._asyncMap); module.exports.mapSeries = internals.doSeries(internals._asyncMap); module.exports.mapLimit = function (arr, limit, iterator, callback) { return internals._mapLimit(limit)(arr, iterator, callback); }; module.exports.filter = internals.doParallel(internals._filter); module.exports.filterSeries = internals.doSeries(internals._filter); module.exports.reject = internals.doParallel(internals._reject); module.exports.rejectSeries = internals.doSeries(internals._reject); // reduce() only has a series version. // A parallel reduce() won't work in many situations. module.exports.reduce = function (arr, memo, iterator, callback) { module.exports.eachSeries(arr, function (item, callback) { iterator(memo, item, function (err, value) { memo = value; callback(err); }); }, function (err) { callback(err, memo); }); }; module.exports.reduceRight = function (arr, memo, iterator, callback) { var reversed = []; for (var i = arr.length - 1; i >= 0; --i) { reversed.push(arr[i]); } module.exports.reduce(reversed, memo, iterator, callback); }; module.exports.detect = internals.doParallel(internals._detect); module.exports.detectSeries = internals.doSeries(internals._detect); module.exports.sortBy = function (arr, iterator, callback) { module.exports.map(arr, function (item, callback) { iterator(item, function (err, criteria) { if (err) { return callback(err); } callback(null, { value: item, criteria: criteria }); }); }, function (err, results) { if (err) { return callback(err); } results.sort(function (left, right) { var a = left.criteria; var b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }); results = internals._unmap(results); callback(null, results); }); }; module.exports.some = function (arr, iterator, callback) { module.exports.each(arr, function (item, cb) { iterator(item, function (err, value) { if (err) { callback(err); callback = Util.noop; } else if (value) { callback(null, true); callback = Util.noop; } cb(); }); }, function (err) { callback(err, false); }); }; module.exports.every = function (arr, iterator, callback) { module.exports.each(arr, function (item, cb) { iterator(item, function (err, value) { if (err) { callback(err); callback = Util.noop; } else if (!value) { callback(null, false); callback = Util.noop; } cb(); }); }, function (err) { callback(err, true); }); }; module.exports.concat = internals.doParallel(internals._concat); module.exports.concatSeries = internals.doSeries(internals._concat);