(function (global, factory) { /*jshint -W030 */ 'use strict'; typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : global.async ? factory(global.neo_async = global.neo_async || {}) : factory(global.async = global.async || {}); }(this, function(exports) { 'use strict'; var noop = function noop() {}; var throwError = function throwError() { throw new Error('Callback was already called.'); }; var DEFAULT_TIMES = 5; var DEFAULT_INTERVAL = 0; var obj = 'object'; var func = 'function'; var isArray = Array.isArray; var nativeKeys = Object.keys; var nativePush = Array.prototype.push; var iteratorSymbol = typeof Symbol === func && Symbol.iterator; var nextTick, asyncNextTick, asyncSetImmediate; createImmediate(); /** * @memberof async * @namespace each * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(); * }, num * 10); * }; * async.each(array, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 2, 3] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(); * }, num * 10); * }; * async.each(array, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [[1, 0], [2, 2], [3, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(); * }, num * 10); * }; * async.each(object, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 2, 3] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(); * }, num * 10); * }; * async.each(object, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']] * }); * * @example * * // break * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num !== 2); * }, num * 10); * }; * async.each(array, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 2] * }); * */ var each = createEach(arrayEach, baseEach, symbolEach); /** * @memberof async * @namespace map * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.map(array, iterator, function(err, res) { * console.log(res); // [1, 3, 2]; * console.log(order); // [1, 2, 3] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.map(array, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [[1, 0], [2, 2], [3, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.map(object, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [1, 2, 3] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.map(object, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']] * }); * */ var map = createMap(arrayEachIndex, baseEachIndex, symbolEachIndex, true); /** * @memberof async * @namespace mapValues * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapValues(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3, '2': 2 } * console.log(order); // [1, 2, 3] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.mapValues(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3, '2': 2 } * console.log(order); // [[1, 0], [2, 2], [3, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapValues(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3, c: 2 } * console.log(order); // [1, 2, 3] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.mapValues(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3, c: 2 } * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']] * }); * */ var mapValues = createMap(arrayEachIndex, baseEachKey, symbolEachKey, false); /** * @memberof async * @namespace filter * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.filter(array, iterator, function(err, res) { * console.log(res); // [1, 3]; * console.log(order); // [1, 2, 3] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.filter(array, iterator, function(err, res) { * console.log(res); // [1, 3]; * console.log(order); // [[1, 0], [2, 2], [3, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.filter(object, iterator, function(err, res) { * console.log(res); // [1, 3]; * console.log(order); // [1, 2, 3] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.filter(object, iterator, function(err, res) { * console.log(res); // [1, 3]; * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']] * }); * */ var filter = createFilter(arrayEachIndexValue, baseEachIndexValue, symbolEachIndexValue, true); /** * @memberof async * @namespace filterSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.filterSeries(array, iterator, function(err, res) { * console.log(res); // [1, 3]; * console.log(order); // [1, 3, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.filterSeries(array, iterator, function(err, res) { * console.log(res); // [1, 3] * console.log(order); // [[1, 0], [3, 1], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.filterSeries(object, iterator, function(err, res) { * console.log(res); // [1, 3] * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.filterSeries(object, iterator, function(err, res) { * console.log(res); // [1, 3] * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']] * }); * */ var filterSeries = createFilterSeries(true); /** * @memberof async * @namespace filterLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.filterLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.filterLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3] * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.filterLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.filterLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3] * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ var filterLimit = createFilterLimit(true); /** * @memberof async * @namespace reject * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.reject(array, iterator, function(err, res) { * console.log(res); // [2]; * console.log(order); // [1, 2, 3] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.reject(array, iterator, function(err, res) { * console.log(res); // [2]; * console.log(order); // [[1, 0], [2, 2], [3, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.reject(object, iterator, function(err, res) { * console.log(res); // [2]; * console.log(order); // [1, 2, 3] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.reject(object, iterator, function(err, res) { * console.log(res); // [2]; * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']] * }); * */ var reject = createFilter(arrayEachIndexValue, baseEachIndexValue, symbolEachIndexValue, false); /** * @memberof async * @namespace rejectSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.rejectSeries(array, iterator, function(err, res) { * console.log(res); // [2]; * console.log(order); // [1, 3, 2] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.rejectSeries(object, iterator, function(err, res) { * console.log(res); // [2]; * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.rejectSeries(object, iterator, function(err, res) { * console.log(res); // [2]; * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']] * }); * */ var rejectSeries = createFilterSeries(false); /** * @memberof async * @namespace rejectLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.rejectLimit(array, 2, iterator, function(err, res) { * console.log(res); // [4, 2] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.rejectLimit(array, 2, iterator, function(err, res) { * console.log(res); // [4, 2] * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.rejectLimit(object, 2, iterator, function(err, res) { * console.log(res); // [4, 2] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.rejectLimit(object, 2, iterator, function(err, res) { * console.log(res); // [4, 2] * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ var rejectLimit = createFilterLimit(false); /** * @memberof async * @namespace detect * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.detect(array, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [1] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.detect(array, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [[1, 0]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.detect(object, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [1] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.detect(object, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [[1, 'a']] * }); * */ var detect = createDetect(arrayEachValue, baseEachValue, symbolEachValue, true); /** * @memberof async * @namespace detectSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.detectSeries(array, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [1] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.detectSeries(array, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [[1, 0]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.detectSeries(object, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [1] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.detectSeries(object, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [[1, 'a']] * }); * */ var detectSeries = createDetectSeries(true); /** * @memberof async * @namespace detectLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.detectLimit(array, 2, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [1] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.detectLimit(array, 2, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [[1, 0]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.detectLimit(object, 2, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [1] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.detectLimit(object, 2, iterator, function(err, res) { * console.log(res); // 1 * console.log(order); // [[1, 'a']] * }); * */ var detectLimit = createDetectLimit(true); /** * @memberof async * @namespace every * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.every(array, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [1, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.every(array, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [[1, 0], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.every(object, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [1, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.every(object, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [[1, 'a'], [2, 'c']] * }); * */ var every = createEvery(arrayEachValue, baseEachValue, symbolEachValue); /** * @memberof async * @namespace everySeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.everySeries(array, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [1, 3, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.everySeries(array, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [[1, 0], [3, 1], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.everySeries(object, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.everySeries(object, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [[1, 'a'], [3, 'b'] [2, 'c']] * }); * */ var everySeries = createEverySeries(); /** * @memberof async * @namespace everyLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.everyLimit(array, 2, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [1, 3, 5, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.everyLimit(array, 2, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.everyLimit(object, 2, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [1, 3, 5, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.everyLimit(object, 2, iterator, function(err, res) { * console.log(res); // false * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e']] * }); * */ var everyLimit = createEveryLimit(); /** * @memberof async * @namespace pick * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.pick(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3 } * console.log(order); // [1, 2, 3, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.pick(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3 } * console.log(order); // [[0, 1], [2, 2], [3, 1], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.pick(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3 } * console.log(order); // [1, 2, 3, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.pick(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3 } * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b'], [4, 'd']] * }); * */ var pick = createPick(arrayEachIndexValue, baseEachKeyValue, symbolEachKeyValue, true); /** * @memberof async * @namespace pickSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.pickSeries(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3 } * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.pickSeries(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3 } * console.log(order); // [[0, 1], [3, 1], [2, 2], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.pickSeries(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3 } * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.pickSeries(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3 } * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c'], [4, 'd']] * }); * */ var pickSeries = createPickSeries(true); /** * @memberof async * @namespace pickLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.pickLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 5, '2': 3 } * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.pickLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 5, '2': 3 } * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.pickLimit(object, 2, iterator, function(err, res) { * console.log(res); // { a: 1, b: 5, c: 3 } * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.pickLimit(object, 2, iterator, function(err, res) { * console.log(res); // { a: 1, b: 5, c: 3 } * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ var pickLimit = createPickLimit(true); /** * @memberof async * @namespace omit * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.omit(array, iterator, function(err, res) { * console.log(res); // { '2': 2, '3': 4 } * console.log(order); // [1, 2, 3, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.omit(array, iterator, function(err, res) { * console.log(res); // { '2': 2, '3': 4 } * console.log(order); // [[0, 1], [2, 2], [3, 1], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.omit(object, iterator, function(err, res) { * console.log(res); // { c: 2, d: 4 } * console.log(order); // [1, 2, 3, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.omit(object, iterator, function(err, res) { * console.log(res); // { c: 2, d: 4 } * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b'], [4, 'd']] * }); * */ var omit = createPick(arrayEachIndexValue, baseEachKeyValue, symbolEachKeyValue, false); /** * @memberof async * @namespace omitSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.omitSeries(array, iterator, function(err, res) { * console.log(res); // { '2': 2, '3': 4 } * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2, 4]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.omitSeries(array, iterator, function(err, res) { * console.log(res); // { '2': 2, '3': 4 } * console.log(order); // [[0, 1], [3, 1], [2, 2], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.omitSeries(object, iterator, function(err, res) { * console.log(res); // { c: 2, d: 4 } * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.omitSeries(object, iterator, function(err, res) { * console.log(res); // { c: 2, d: 4 } * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c'], [4, 'd']] * }); * */ var omitSeries = createPickSeries(false); /** * @memberof async * @namespace omitLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.omitLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '3': 4, '4': 2 } * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.omitLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '3': 4, '4': 2 } * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.omitLimit(object, 2, iterator, function(err, res) { * console.log(res); // { d: 4, e: 2 } * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.omitLimit(object, 2, iterator, function(err, res) { * console.log(res); // { d: 4, e: 2 } * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ var omitLimit = createPickLimit(false); /** * @memberof async * @namespace transform * @param {Array|Object} collection * @param {Array|Object|Function} [accumulator] * @param {Function} [iterator] * @param {Function} [callback] * @example * * // array * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * result.push(num) * done(); * }, num * 10); * }; * async.transform(collection, iterator, function(err, res) { * console.log(res); // [1, 2, 3, 4] * console.log(order); // [1, 2, 3, 4] * }); * * @example * * // array with index and accumulator * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, index, done) { * setTimeout(function() { * order.push([num, index]); * result[index] = num; * done(); * }, num * 10); * }; * async.transform(collection, {}, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3, '2': 2, '3': 4 } * console.log(order); // [[1, 0], [2, 2], [3, 1], [4, 3]] * }); * * @example * * // object with accumulator * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * result.push(num); * done(); * }, num * 10); * }; * async.transform(collection, [], iterator, function(err, res) { * console.log(res); // [1, 2, 3, 4] * console.log(order); // [1, 2, 3, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, key, done) { * setTimeout(function() { * order.push([num, key]); * result[key] = num; * done(); * }, num * 10); * }; * async.transform(collection, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3, c: 2, d: 4 } * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b'], [4, 'd']] * }); * */ var transform = createTransform(arrayEachResult, baseEachResult, symbolEachResult); /** * @memberof async * @namespace sortBy * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.sortBy(array, iterator, function(err, res) { * console.log(res); // [1, 2, 3]; * console.log(order); // [1, 2, 3] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.sortBy(array, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [[1, 0], [2, 2], [3, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.sortBy(object, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [1, 2, 3] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.sortBy(object, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']] * }); * */ var sortBy = createSortBy(arrayEachIndexValue, baseEachIndexValue, symbolEachIndexValue); /** * @memberof async * @namespace concat * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, [num]); * }, num * 10); * }; * async.concat(array, iterator, function(err, res) { * console.log(res); // [1, 2, 3]; * console.log(order); // [1, 2, 3] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, [num]); * }, num * 10); * }; * async.concat(array, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [[1, 0], [2, 2], [3, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, [num]); * }, num * 10); * }; * async.concat(object, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [1, 2, 3] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, [num]); * }, num * 10); * }; * async.concat(object, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']] * }); * */ var concat = createConcat(arrayEachIndex, baseEachIndex, symbolEachIndex); /** * @memberof async * @namespace groupBy * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [4.2, 6.4, 6.1]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBy(array, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.1, 6.4] } * console.log(order); // [4.2, 6.1, 6.4] * }); * * @example * * // array with index * var order = []; * var array = [4.2, 6.4, 6.1]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBy(array, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.1, 6.4] } * console.log(order); // [[4.2, 0], [6.1, 2], [6.4, 1]] * }); * * @example * * // object * var order = []; * var object = { a: 4.2, b: 6.4, c: 6.1 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBy(object, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.1, 6.4] } * console.log(order); // [4.2, 6.1, 6.4] * }); * * @example * * // object with key * var order = []; * var object = { a: 4.2, b: 6.4, c: 6.1 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBy(object, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.1, 6.4] } * console.log(order); // [[4.2, 'a'], [6.1, 'c'], [6.4, 'b']] * }); * */ var groupBy = createGroupBy(arrayEachValue, baseEachValue, symbolEachValue); /** * @memberof async * @namespace parallel * @param {Array|Object} tasks - functions * @param {Function} callback * @example * * var order = []; * var tasks = [ * function(done) { * setTimeout(function() { * order.push(1); * done(null, 1); * }, 10); * }, * function(done) { * setTimeout(function() { * order.push(2); * done(null, 2); * }, 30); * }, * function(done) { * setTimeout(function() { * order.push(3); * done(null, 3); * }, 40); * }, * function(done) { * setTimeout(function() { * order.push(4); * done(null, 4); * }, 20); * } * ]; * async.parallel(tasks, function(err, res) { * console.log(res); // [1, 2, 3, 4]; * console.log(order); // [1, 4, 2, 3] * }); * * @example * * var order = []; * var tasks = { * 'a': function(done) { * setTimeout(function() { * order.push(1); * done(null, 1); * }, 10); * }, * 'b': function(done) { * setTimeout(function() { * order.push(2); * done(null, 2); * }, 30); * }, * 'c': function(done) { * setTimeout(function() { * order.push(3); * done(null, 3); * }, 40); * }, * 'd': function(done) { * setTimeout(function() { * order.push(4); * done(null, 4); * }, 20); * } * }; * async.parallel(tasks, function(err, res) { * console.log(res); // { a: 1, b: 2, c: 3, d:4 } * console.log(order); // [1, 4, 2, 3] * }); * */ var parallel = createParallel(arrayEachFunc, baseEachFunc); /** * @memberof async * @namespace applyEach */ var applyEach = createApplyEach(map); /** * @memberof async * @namespace applyEachSeries */ var applyEachSeries = createApplyEach(mapSeries); /** * @memberof async * @namespace log */ var log = createLogger('log'); /** * @memberof async * @namespace dir */ var dir = createLogger('dir'); /** * @version 2.5.1 * @namespace async */ var index = { VERSION: '2.5.1', // Collections each: each, eachSeries: eachSeries, eachLimit: eachLimit, forEach: each, forEachSeries: eachSeries, forEachLimit: eachLimit, eachOf: each, eachOfSeries: eachSeries, eachOfLimit: eachLimit, forEachOf: each, forEachOfSeries: eachSeries, forEachOfLimit: eachLimit, map: map, mapSeries: mapSeries, mapLimit: mapLimit, mapValues: mapValues, mapValuesSeries: mapValuesSeries, mapValuesLimit: mapValuesLimit, filter: filter, filterSeries: filterSeries, filterLimit: filterLimit, select: filter, selectSeries: filterSeries, selectLimit: filterLimit, reject: reject, rejectSeries: rejectSeries, rejectLimit: rejectLimit, detect: detect, detectSeries: detectSeries, detectLimit: detectLimit, find: detect, findSeries: detectSeries, findLimit: detectLimit, pick: pick, pickSeries: pickSeries, pickLimit: pickLimit, omit: omit, omitSeries: omitSeries, omitLimit: omitLimit, reduce: reduce, inject: reduce, foldl: reduce, reduceRight: reduceRight, foldr: reduceRight, transform: transform, transformSeries: transformSeries, transformLimit: transformLimit, sortBy: sortBy, sortBySeries: sortBySeries, sortByLimit: sortByLimit, some: some, someSeries: someSeries, someLimit: someLimit, any: some, anySeries: someSeries, anyLimit: someLimit, every: every, everySeries: everySeries, everyLimit: everyLimit, all: every, allSeries: everySeries, allLimit: everyLimit, concat: concat, concatSeries: concatSeries, concatLimit: concatLimit, groupBy: groupBy, groupBySeries: groupBySeries, groupByLimit: groupByLimit, // Control Flow parallel: parallel, series: series, parallelLimit: parallelLimit, tryEach: tryEach, waterfall: waterfall, angelFall: angelFall, angelfall: angelFall, whilst: whilst, doWhilst: doWhilst, until: until, doUntil: doUntil, during: during, doDuring: doDuring, forever: forever, compose: compose, seq: seq, applyEach: applyEach, applyEachSeries: applyEachSeries, queue: queue, priorityQueue: priorityQueue, cargo: cargo, auto: auto, autoInject: autoInject, retry: retry, retryable: retryable, iterator: iterator, times: times, timesSeries: timesSeries, timesLimit: timesLimit, race: race, // Utils apply: apply, nextTick: asyncNextTick, setImmediate: asyncSetImmediate, memoize: memoize, unmemoize: unmemoize, ensureAsync: ensureAsync, constant: constant, asyncify: asyncify, wrapSync: asyncify, log: log, dir: dir, reflect: reflect, reflectAll: reflectAll, timeout: timeout, createLogger: createLogger, // Mode safe: safe, fast: fast }; exports['default'] = index; baseEachSync(index, function(func, key) { exports[key] = func; }, nativeKeys(index)); /** * @private */ function createImmediate(safeMode) { var delay = function delay(fn) { var args = slice(arguments, 1); setTimeout(function() { fn.apply(null, args); }); }; asyncSetImmediate = typeof setImmediate === func ? setImmediate : delay; if (typeof process === obj && typeof process.nextTick === func) { nextTick = /^v0.10/.test(process.version) ? asyncSetImmediate : process.nextTick; asyncNextTick = /^v0/.test(process.version) ? asyncSetImmediate : process.nextTick; } else { asyncNextTick = nextTick = asyncSetImmediate; } if (safeMode === false) { nextTick = function(cb) { cb(); }; } } /* sync functions based on lodash */ /** * Converts `arguments` to an array. * * @private * @param {Array} array = The array to slice. */ function createArray(array) { var index = -1; var size = array.length; var result = Array(size); while (++index < size) { result[index] = array[index]; } return result; } /** * Create an array from `start` * * @private * @param {Array} array - The array to slice. * @param {number} start - The start position. */ function slice(array, start) { var end = array.length; var index = -1; var size = end - start; if (size <= 0) { return []; } var result = Array(size); while (++index < size) { result[index] = array[index + start]; } return result; } /** * @private * @param {Object} object */ function objectClone(object) { var keys = nativeKeys(object); var size = keys.length; var index = -1; var result = {}; while (++index < size) { var key = keys[index]; result[key] = object[key]; } return result; } /** * Create an array with all falsey values removed. * * @private * @param {Array} array - The array to compact. */ function compact(array) { var index = -1; var size = array.length; var result = []; while (++index < size) { var value = array[index]; if (value) { result[result.length] = value; } } return result; } /** * Create an array of reverse sequence. * * @private * @param {Array} array - The array to reverse. */ function reverse(array) { var index = -1; var size = array.length; var result = Array(size); var resIndex = size; while (++index < size) { result[--resIndex] = array[index]; } return result; } /** * Checks if key exists in object property. * * @private * @param {Object} object - The object to inspect. * @param {string} key - The key to check. */ function has(object, key) { return object.hasOwnProperty(key); } /** * Check if target exists in array. * @private * @param {Array} array * @param {*} target */ function notInclude(array, target) { var index = -1; var size = array.length; while(++index < size) { if (array[index] === target) { return false; } } return true; } /** * @private * @param {Array} array - The array to iterate over. * @param {Function} iterator - The function invoked per iteration. */ function arrayEachSync(array, iterator) { var index = -1; var size = array.length; while (++index < size) { iterator(array[index], index); } return array; } /** * @private * @param {Object} object - The object to iterate over. * @param {Function} iterator - The function invoked per iteration. * @param {Array} keys */ function baseEachSync(object, iterator, keys) { var index = -1; var size = keys.length; while (++index < size) { var key = keys[index]; iterator(object[key], key); } return object; } /** * @private * @param {number} n * @param {Function} iterator */ function timesSync(n, iterator) { var index = -1; while (++index < n) { iterator(index); } } /** * @private * @param {Array} array * @param {number[]} criteria */ function sortByCriteria(array, criteria) { var l = array.length; var indices = Array(l); var i; for (i = 0; i < l; i++) { indices[i] = i; } quickSort(criteria, 0, l - 1, indices); var result = Array(l); for (var n = 0; n < l; n++) { i = indices[n]; result[n] = i === undefined ? array[n] : array[i]; } return result; } function partition(array, i, j, mid, indices) { var l = i; var r = j; while (l <= r) { i = l; while (l < r && array[l] < mid) { l++; } while (r >= i && array[r] >= mid) { r--; } if (l > r) { break; } swap(array, indices, l++, r--); } return l; } function swap(array, indices, l, r) { var n = array[l]; array[l] = array[r]; array[r] = n; var i = indices[l]; indices[l] = indices[r]; indices[r] = i; } function quickSort(array, i, j, indices) { if (i === j) { return; } var k = i; while (++k <= j && array[i] === array[k]) { var l = k - 1; if (indices[l] > indices[k]) { var index = indices[l]; indices[l] = indices[k]; indices[k] = index; } } if (k > j) { return; } var p = array[i] > array[k] ? i : k; k = partition(array, i, j, array[p], indices); quickSort(array, i, k - 1, indices); quickSort(array, k, j, indices); } /** * @Private */ function makeConcatResult(array) { var result = []; arrayEachSync(array, function(value) { if (value === noop) { return; } if (isArray(value)) { nativePush.apply(result, value); } else { result.push(value); } }); return result; } /* async functions */ /** * @private */ function arrayEach(array, iterator, callback) { var index = -1; var size = array.length; if (iterator.length === 3) { while (++index < size) { iterator(array[index], index, onlyOnce(callback)); } } else { while (++index < size) { iterator(array[index], onlyOnce(callback)); } } } /** * @private */ function baseEach(object, iterator, callback, keys) { var key; var index = -1; var size = keys.length; if (iterator.length === 3) { while (++index < size) { key = keys[index]; iterator(object[key], key, onlyOnce(callback)); } } else { while (++index < size) { iterator(object[keys[index]], onlyOnce(callback)); } } } /** * @private */ function symbolEach(collection, iterator, callback) { var iter = collection[iteratorSymbol](); var index = -1; var item; if (iterator.length === 3) { while ((item = iter.next()).done === false) { iterator(item.value, ++index, onlyOnce(callback)); } } else { while ((item = iter.next()).done === false) { iterator(item.value, onlyOnce(callback)); } } } /** * @private */ function arrayEachResult(array, result, iterator, callback) { var index = -1; var size = array.length; if (iterator.length === 4) { while (++index < size) { iterator(result, array[index], index, onlyOnce(callback)); } } else { while (++index < size) { iterator(result, array[index], onlyOnce(callback)); } } } /** * @private */ function baseEachResult(object, result, iterator, callback, keys) { var key; var index = -1; var size = keys.length; if (iterator.length === 4) { while (++index < size) { key = keys[index]; iterator(result, object[key], key, onlyOnce(callback)); } } else { while (++index < size) { iterator(result, object[keys[index]], onlyOnce(callback)); } } } /** * @private */ function symbolEachResult(collection, result, iterator, callback) { var item; var index = -1; var iter = collection[iteratorSymbol](); if (iterator.length === 4) { while ((item = iter.next()).done === false) { iterator(result, item.value, ++index, onlyOnce(callback)); } } else { while ((item = iter.next()).done === false) { iterator(result, item.value, onlyOnce(callback)); } } } /** * @private */ function arrayEachFunc(array, createCallback) { var index = -1; var size = array.length; while (++index < size) { array[index](createCallback(index)); } } /** * @private */ function baseEachFunc(object, createCallback, keys) { var key; var index = -1; var size = keys.length; while (++index < size) { key = keys[index]; object[key](createCallback(key)); } } /** * @private */ function arrayEachIndex(array, iterator, createCallback) { var index = -1; var size = array.length; if (iterator.length === 3) { while (++index < size) { iterator(array[index], index, createCallback(index)); } } else { while (++index < size) { iterator(array[index], createCallback(index)); } } } /** * @private */ function baseEachIndex(object, iterator, createCallback, keys) { var key; var index = -1; var size = keys.length; if (iterator.length === 3) { while (++index < size) { key = keys[index]; iterator(object[key], key, createCallback(index)); } } else { while (++index < size) { iterator(object[keys[index]], createCallback(index)); } } } /** * @private */ function symbolEachIndex(collection, iterator, createCallback) { var values; var index = -1; var size = collection.size; var iter = collection[iteratorSymbol](); if (iterator.length === 3) { while (++index < size) { values = iter.next().value; iterator(values, index, createCallback(index)); } } else { while (++index < size) { iterator(iter.next().value, createCallback(index)); } } } /** * @private */ function baseEachKey(object, iterator, createCallback, keys) { var key; var index = -1; var size = keys.length; if (iterator.length === 3) { while (++index < size) { key = keys[index]; iterator(object[key], key, createCallback(key)); } } else { while (++index < size) { key = keys[index]; iterator(object[key], createCallback(key)); } } } /** * @private */ function symbolEachKey(collection, iterator, createCallback) { var item; var index = -1; var iter = collection[iteratorSymbol](); if (iterator.length === 3) { while ((item = iter.next()).done === false) { iterator(item.value, ++index, createCallback(index)); } } else { while ((item = iter.next()).done === false) { iterator(item.value, createCallback(++index)); } } } /** * @private */ function arrayEachValue(array, iterator, createCallback) { var value; var index = -1; var size = array.length; if (iterator.length === 3) { while (++index < size) { value = array[index]; iterator(value, index, createCallback(value)); } } else { while (++index < size) { value = array[index]; iterator(value, createCallback(value)); } } } /** * @private */ function baseEachValue(object, iterator, createCallback, keys) { var key, value; var index = -1; var size = keys.length; if (iterator.length === 3) { while (++index < size) { key = keys[index]; value = object[key]; iterator(value, key, createCallback(value)); } } else { while (++index < size) { value = object[keys[index]]; iterator(value, createCallback(value)); } } } /** * @private */ function symbolEachValue(collection, iterator, createCallback) { var value, item; var index = -1; var iter = collection[iteratorSymbol](); if (iterator.length === 3) { while ((item = iter.next()).done === false) { value = item.value; iterator(value, ++index, createCallback(value)); } } else { while ((item = iter.next()).done === false) { value = item.value; iterator(value, createCallback(value)); } } } /** * @private */ function arrayEachIndexValue(array, iterator, createCallback) { var value; var index = -1; var size = array.length; if (iterator.length === 3) { while (++index < size) { value = array[index]; iterator(value, index, createCallback(index, value)); } } else { while (++index < size) { value = array[index]; iterator(value, createCallback(index, value)); } } } /** * @private */ function baseEachIndexValue(object, iterator, createCallback, keys) { var key, value; var index = -1; var size = keys.length; if (iterator.length === 3) { while (++index < size) { key = keys[index]; value = object[key]; iterator(value, key, createCallback(index, value)); } } else { while (++index < size) { value = object[keys[index]]; iterator(value, createCallback(index, value)); } } } /** * @private */ function symbolEachIndexValue(collection, iterator, createCallback) { var value, item; var index = -1; var iter = collection[iteratorSymbol](); if (iterator.length === 3) { while ((item = iter.next()).done === false) { value = item.value; iterator(value, ++index, createCallback(index, value)); } } else { while ((item = iter.next()).done === false) { value = item.value; iterator(value, createCallback(++index, value)); } } } /** * @private */ function baseEachKeyValue(object, iterator, createCallback, keys) { var key, value; var index = -1; var size = keys.length; if (iterator.length === 3) { while (++index < size) { key = keys[index]; value = object[key]; iterator(value, key, createCallback(key, value)); } } else { while (++index < size) { key = keys[index]; value = object[key]; iterator(value, createCallback(key, value)); } } } /** * @private */ function symbolEachKeyValue(collection, iterator, createCallback) { var value, item; var index = -1; var iter = collection[iteratorSymbol](); if (iterator.length === 3) { while ((item = iter.next()).done === false) { value = item.value; iterator(value, ++index, createCallback(index, value)); } } else { while ((item = iter.next()).done === false) { value = item.value; iterator(value, createCallback(++index, value)); } } } /** * @private * @param {Function} func */ function onlyOnce(func) { return function(err, res) { var fn = func; func = throwError; fn(err, res); }; } /** * @private * @param {Function} func */ function once(func) { return function(err, res) { var fn = func; func = noop; fn(err, res); }; } /** * @private * @param {Function} arrayEach * @param {Function} baseEach */ function createEach(arrayEach, baseEach, symbolEach) { return function each(collection, iterator, callback) { callback = callback || noop; var size, keys; var completed = 0; if (isArray(collection)) { size = collection.length; arrayEach(collection, iterator, done); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; symbolEach(collection, iterator, done); } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; baseEach(collection, iterator, done, keys); } if (!size) { callback(null); } function done(err, bool) { if (err) { callback = once(callback); callback(err); } else if (++completed === size) { callback(null); } else if (bool === false) { callback = once(callback); callback(null); } } }; } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach */ function createMap(arrayEach, baseEach, symbolEach, useArray) { var init, clone; if (useArray) { init = Array; clone = createArray; } else { init = function() { return {}; }; clone = objectClone; } return function(collection, iterator, callback) { callback = callback || noop; var size, keys, result; var completed = 0; if (isArray(collection)) { size = collection.length; result = init(size); arrayEach(collection, iterator, createCallback); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; result = init(size); symbolEach(collection, iterator, createCallback); } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; result = init(size); baseEach(collection, iterator, createCallback, keys); } if (!size) { callback(null, init()); } function createCallback(key) { return function done(err, res) { if (key === null) { throwError(); } if (err) { key = null; callback = once(callback); callback(err, clone(result)); return; } result[key] = res; key = null; if (++completed === size) { callback(null, result); } }; } }; } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach * @param {boolean} bool */ function createFilter(arrayEach, baseEach, symbolEach, bool) { return function(collection, iterator, callback) { callback = callback || noop; var size, keys, result; var completed = 0; if (isArray(collection)) { size = collection.length; result = Array(size); arrayEach(collection, iterator, createCallback); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; result = Array(size); symbolEach(collection, iterator, createCallback); } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; result = Array(size); baseEach(collection, iterator, createCallback, keys); } if (!size) { return callback(null, []); } function createCallback(index, value) { return function done(err, res) { if (index === null) { throwError(); } if (err) { index = null; callback = once(callback); callback(err); return; } if (!!res === bool) { result[index] = value; } index = null; if (++completed === size) { callback(null, compact(result)); } }; } }; } /** * @private * @param {boolean} bool */ function createFilterSeries(bool) { return function(collection, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, value, keys, iter, iterate; var sync = false; var completed = 0; var result = []; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, []); } iterate(); function arrayIterator() { value = collection[completed]; iterator(value, done); } function arrayIteratorWithIndex() { value = collection[completed]; iterator(value, completed, done); } function symbolIterator() { value = iter.next().value; iterator(value, done); } function symbolIteratorWithKey() { value = iter.next().value; iterator(value, completed, done); } function objectIterator() { key = keys[completed]; value = collection[key]; iterator(value, done); } function objectIteratorWithKey() { key = keys[completed]; value = collection[key]; iterator(value, key, done); } function done(err, res) { if (err) { callback(err); return; } if (!!res === bool) { result[result.length] = value; } if (++completed === size) { iterate = throwError; callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } }; } /** * @private * @param {boolean} bool */ function createFilterLimit(bool) { return function(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, value, keys, iter, item, iterate, result; var sync = false; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, []); } result = Array(size); timesSync(limit > size ? size : limit, iterate); function arrayIterator() { index = started++; if (index < size) { value = collection[index]; iterator(value, createCallback(value, index)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { value = collection[index]; iterator(value, index, createCallback(value, index)); } } function symbolIterator() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, createCallback(value, started++)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, started, createCallback(value, started++)); } } function objectIterator() { index = started++; if (index < size) { value = collection[keys[index]]; iterator(value, createCallback(value, index)); } } function objectIteratorWithKey() { index = started++; if (index < size) { key = keys[index]; value = collection[key]; iterator(value, key, createCallback(value, index)); } } function createCallback(value, index) { return function(err, res) { if (index === null) { throwError(); } if (err) { index = null; iterate = noop; callback = once(callback); callback(err); return; } if (!!res === bool) { result[index] = value; } index = null; if (++completed === size) { callback = onlyOnce(callback); callback(null, compact(result)); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } }; } /** * @memberof async * @namespace eachSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(); * }, num * 10); * }; * async.eachSeries(array, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 3, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(); * }, num * 10); * }; * async.eachSeries(array, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [[1, 0], [3, 1], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(); * }, num * 10); * }; * async.eachSeries(object, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(); * }, num * 10); * }; * async.eachSeries(object, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'b']] * }); * * @example * * // break * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num !== 3); * }, num * 10); * }; * async.eachSeries(array, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 3] * }); */ function eachSeries(collection, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, keys, iter, value, iterate; var sync = false; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null); } iterate(); function arrayIterator() { iterator(collection[completed], done); } function arrayIteratorWithIndex() { iterator(collection[completed], completed, done); } function symbolIterator() { iterator(iter.next().value, done); } function symbolIteratorWithKey() { value = iter.next().value; iterator(value, completed, done); } function objectIterator() { iterator(collection[keys[completed]], done); } function objectIteratorWithKey() { key = keys[completed]; iterator(collection[key], key, done); } function done(err, bool) { if (err) { callback(err); } else if (++completed === size) { iterate = throwError; callback(null); } else if (bool === false) { iterate = throwError; callback(null); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace eachLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(); * }, num * 10); * }; * async.eachLimit(array, 2, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(); * }, num * 10); * }; * async.eachLimit(array, 2, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(); * }, num * 10); * }; * async.eachLimit(object, 2, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(); * }, num * 10); * }; * async.eachLimit(object, 2, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * * @example * * // break * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num !== 5); * }, num * 10); * }; * async.eachLimit(array, 2, iterator, function(err, res) { * console.log(res); // undefined * console.log(order); // [1, 3, 5] * }); * */ function eachLimit(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, keys, iter, item, iterate; var sync = false; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } else { return callback(null); } if (!size || isNaN(limit) || limit < 1) { return callback(null); } timesSync(limit > size ? size : limit, iterate); function arrayIterator() { if (started < size) { iterator(collection[started++], done); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { iterator(collection[index], index, done); } } function symbolIterator() { if ((item = iter.next()).done === false) { iterator(item.value, done); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { iterator(item.value, started++, done); } } function objectIterator() { if (started < size) { iterator(collection[keys[started++]], done); } } function objectIteratorWithKey() { index = started++; if (index < size) { key = keys[index]; iterator(collection[key], key, done); } } function done(err, bool) { if (err) { iterate = noop; callback = once(callback); callback(err); } else if (++completed === size) { iterate = throwError; callback = onlyOnce(callback); callback(null); } else if (bool === false) { iterate = noop; callback = once(callback); callback(null); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace mapSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapSeries(array, iterator, function(err, res) { * console.log(res); // [1, 3, 2]; * console.log(order); // [1, 3, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.mapSeries(array, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [[1, 0], [3, 1], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapSeries(object, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.mapSeries(object, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']] * }); * */ function mapSeries(collection, iterator, callback) { callback = callback || noop; var size, key, keys, iter, value, result, iterate; var sync = false; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, []); } result = Array(size); iterate(); function arrayIterator() { iterator(collection[completed], done); } function arrayIteratorWithIndex() { iterator(collection[completed], completed, done); } function symbolIterator() { iterator(iter.next().value, done); } function symbolIteratorWithKey() { value = iter.next().value; iterator(value, completed, done); } function objectIterator() { iterator(collection[keys[completed]], done); } function objectIteratorWithKey() { key = keys[completed]; iterator(collection[key], key, done); } function done(err, res) { if (err) { iterate = throwError; callback = onlyOnce(callback); callback(err, createArray(result)); return; } result[completed] = res; if (++completed === size) { iterate = throwError; callback(null, result); callback = throwError; } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace mapLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3, 4, 2] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.mapLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3, 4, 2] * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3, 4, 2] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.mapLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 5, 3, 4, 2] * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ function mapLimit(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, keys, iter, item, result, iterate; var sync = false; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, []); } result = Array(size); timesSync(limit > size ? size : limit, iterate); function arrayIterator() { index = started++; if (index < size) { iterator(collection[index], createCallback(index)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { iterator(collection[index], index, createCallback(index)); } } function symbolIterator() { if ((item = iter.next()).done === false) { iterator(item.value, createCallback(started++)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { iterator(item.value, started, createCallback(started++)); } } function objectIterator() { index = started++; if (index < size) { iterator(collection[keys[index]], createCallback(index)); } } function objectIteratorWithKey() { index = started++; if (index < size) { key = keys[index]; iterator(collection[key], key, createCallback(index)); } } function createCallback(index) { return function(err, res) { if (index === null) { throwError(); } if (err) { index = null; iterate = noop; callback = once(callback); callback(err, createArray(result)); return; } result[index] = res; index = null; if (++completed === size) { iterate = throwError; callback(null, result); callback = throwError; } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } } /** * @memberof async * @namespace mapValuesSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapValuesSeries(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3, '2': 2 } * console.log(order); // [1, 3, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.mapValuesSeries(array, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3, '2': 2 } * console.log(order); // [[1, 0], [3, 1], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapValuesSeries(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3, c: 2 } * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.mapValuesSeries(object, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3, c: 2 } * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']] * }); * */ function mapValuesSeries(collection, iterator, callback) { callback = callback || noop; var size, key, keys, iter, value, iterate; var sync = false; var result = {}; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, result); } iterate(); function arrayIterator() { key = completed; iterator(collection[completed], done); } function arrayIteratorWithIndex() { key = completed; iterator(collection[completed], completed, done); } function symbolIterator() { key = completed; value = iter.next().value; iterator(value, done); } function symbolIteratorWithKey() { key = completed; value = iter.next().value; iterator(value, completed, done); } function objectIterator() { key = keys[completed]; iterator(collection[key], done); } function objectIteratorWithKey() { key = keys[completed]; iterator(collection[key], key, done); } function done(err, res) { if (err) { iterate = throwError; callback = onlyOnce(callback); callback(err, objectClone(result)); return; } result[key] = res; if (++completed === size) { iterate = throwError; callback(null, result); callback = throwError; } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace mapValuesLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapValuesLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 5, '2': 3, '3': 4, '4': 2 } * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.mapValuesLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 5, '2': 3, '3': 4, '4': 2 } * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.mapValuesLimit(object, 2, iterator, function(err, res) { * console.log(res); // { a: 1, b: 5, c: 3, d: 4, e: 2 } * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.mapValuesLimit(object, 2, iterator, function(err, res) { * console.log(res); // { a: 1, b: 5, c: 3, d: 4, e: 2 } * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ function mapValuesLimit(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, keys, iter, item, iterate; var sync = false; var result = {}; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, result); } timesSync(limit > size ? size : limit, iterate); function arrayIterator() { index = started++; if (index < size) { iterator(collection[index], createCallback(index)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { iterator(collection[index], index, createCallback(index)); } } function symbolIterator() { if ((item = iter.next()).done === false) { iterator(item.value, createCallback(started++)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { iterator(item.value, started, createCallback(started++)); } } function objectIterator() { index = started++; if (index < size) { key = keys[index]; iterator(collection[key], createCallback(key)); } } function objectIteratorWithKey() { index = started++; if (index < size) { key = keys[index]; iterator(collection[key], key, createCallback(key)); } } function createCallback(key) { return function(err, res) { if (key === null) { throwError(); } if (err) { key = null; iterate = noop; callback = once(callback); callback(err, objectClone(result)); return; } result[key] = res; key = null; if (++completed === size) { callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach * @param {boolean} bool */ function createDetect(arrayEach, baseEach, symbolEach, bool) { return function(collection, iterator, callback) { callback = callback || noop; var size, keys; var completed = 0; if (isArray(collection)) { size = collection.length; arrayEach(collection, iterator, createCallback); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; symbolEach(collection, iterator, createCallback); } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; baseEach(collection, iterator, createCallback, keys); } if (!size) { callback(null); } function createCallback(value) { var called = false; return function done(err, res) { if (called) { throwError(); } called = true; if (err) { callback = once(callback); callback(err); } else if (!!res === bool) { callback = once(callback); callback(null, value); } else if (++completed === size) { callback(null); } }; } }; } /** * @private * @param {boolean} bool */ function createDetectSeries(bool) { return function(collection, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, value, keys, iter, iterate; var sync = false; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null); } iterate(); function arrayIterator() { value = collection[completed]; iterator(value, done); } function arrayIteratorWithIndex() { value = collection[completed]; iterator(value, completed, done); } function symbolIterator() { value = iter.next().value; iterator(value, done); } function symbolIteratorWithKey() { value = iter.next().value; iterator(value, completed, done); } function objectIterator() { value = collection[keys[completed]]; iterator(value, done); } function objectIteratorWithKey() { key = keys[completed]; value = collection[key]; iterator(value, key, done); } function done(err, res) { if (err) { callback(err); } else if (!!res === bool) { iterate = throwError; callback(null, value); } else if (++completed === size) { iterate = throwError; callback(null); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } }; } /** * @private * @param {boolean} bool */ function createDetectLimit(bool) { return function(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, value, keys, iter, item, iterate; var sync = false; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null); } timesSync(limit > size ? size : limit, iterate); function arrayIterator() { index = started++; if (index < size) { value = collection[index]; iterator(value, createCallback(value)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { value = collection[index]; iterator(value, index, createCallback(value)); } } function symbolIterator() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, createCallback(value)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, started++, createCallback(value)); } } function objectIterator() { index = started++; if (index < size) { value = collection[keys[index]]; iterator(value, createCallback(value)); } } function objectIteratorWithKey() { if (started < size) { key = keys[started++]; value = collection[key]; iterator(value, key, createCallback(value)); } } function createCallback(value) { var called = false; return function(err, res) { if (called) { throwError(); } called = true; if (err) { iterate = noop; callback = once(callback); callback(err); } else if (!!res === bool) { iterate = noop; callback = once(callback); callback(null, value); } else if (++completed === size) { callback(null); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } }; } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach * @param {boolean} bool */ function createPick(arrayEach, baseEach, symbolEach, bool) { return function(collection, iterator, callback) { callback = callback || noop; var size, keys; var completed = 0; var result = {}; if (isArray(collection)) { size = collection.length; arrayEach(collection, iterator, createCallback); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; symbolEach(collection, iterator, createCallback); } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; baseEach(collection, iterator, createCallback, keys); } if (!size) { return callback(null, {}); } function createCallback(key, value) { return function done(err, res) { if (key === null) { throwError(); } if (err) { key = null; callback = once(callback); callback(err, objectClone(result)); return; } if (!!res === bool) { result[key] = value; } key = null; if (++completed === size) { callback(null, result); } }; } }; } /** * @private * @param {boolean} bool */ function createPickSeries(bool) { return function(collection, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, value, keys, iter, iterate; var sync = false; var result = {}; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, {}); } iterate(); function arrayIterator() { key = completed; value = collection[completed]; iterator(value, done); } function arrayIteratorWithIndex() { key = completed; value = collection[completed]; iterator(value, completed, done); } function symbolIterator() { key = completed; value = iter.next().value; iterator(value, done); } function symbolIteratorWithKey() { key = completed; value = iter.next().value; iterator(value, key, done); } function objectIterator() { key = keys[completed]; value = collection[key]; iterator(value, done); } function objectIteratorWithKey() { key = keys[completed]; value = collection[key]; iterator(value, key, done); } function done(err, res) { if (err) { callback(err, result); return; } if (!!res === bool) { result[key] = value; } if (++completed === size) { iterate = throwError; callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } }; } /** * @private * @param {boolean} bool */ function createPickLimit(bool) { return function(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, value, keys, iter, item, iterate; var sync = false; var result = {}; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, {}); } timesSync(limit > size ? size : limit, iterate); function arrayIterator() { index = started++; if (index < size) { value = collection[index]; iterator(value, createCallback(value, index)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { value = collection[index]; iterator(value, index, createCallback(value, index)); } } function symbolIterator() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, createCallback(value, started++)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, started, createCallback(value, started++)); } } function objectIterator() { if (started < size) { key = keys[started++]; value = collection[key]; iterator(value, createCallback(value, key)); } } function objectIteratorWithKey() { if (started < size) { key = keys[started++]; value = collection[key]; iterator(value, key, createCallback(value, key)); } } function createCallback(value, key) { return function(err, res) { if (key === null) { throwError(); } if (err) { key = null; iterate = noop; callback = once(callback); callback(err, objectClone(result)); return; } if (!!res === bool) { result[key] = value; } key = null; if (++completed === size) { iterate = throwError; callback = onlyOnce(callback); callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } }; } /** * @memberof async * @namespace reduce * @param {Array|Object} collection * @param {*} result * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * done(null, result + num); * }, num * 10); * }; * async.reduce(collection, 0, iterator, function(err, res) { * console.log(res); // 10 * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // array with index * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, result + num); * }, num * 10); * }; * async.reduce(collection, '', iterator, function(err, res) { * console.log(res); // '1324' * console.log(order); // [[1, 0], [3, 1], [2, 2], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * done(null, result + num); * }, num * 10); * }; * async.reduce(collection, '', iterator, function(err, res) { * console.log(res); // '1324' * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, result + num); * }, num * 10); * }; * async.reduce(collection, 0, iterator, function(err, res) { * console.log(res); // 10 * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'b'], [4, 'd']] * }); * */ function reduce(collection, result, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, keys, iter, 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 && collection[iteratorSymbol]) { size = collection.size; 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) { iterator(result, collection[completed], completed, done); } function symbolIterator() { iterator(result, iter.next().value, done); } function symbolIteratorWithKey() { iterator(result, iter.next().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) { if (err) { callback(err, result); } else if (++completed === size) { iterator = throwError; callback(null, result); } else if (sync) { nextTick(function() { iterate(result); }); } else { sync = true; iterate(result); } sync = false; } } /** * @memberof async * @namespace reduceRight * @param {Array|Object} collection * @param {*} result * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * done(null, result + num); * }, num * 10); * }; * async.reduceRight(collection, 0, iterator, function(err, res) { * console.log(res); // 10 * console.log(order); // [4, 2, 3, 1] * }); * * @example * * // array with index * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, result + num); * }, num * 10); * }; * async.reduceRight(collection, '', iterator, function(err, res) { * console.log(res); // '4231' * console.log(order); // [[4, 3], [2, 2], [3, 1], [1, 0]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * done(null, result + num); * }, num * 10); * }; * async.reduceRight(collection, '', iterator, function(err, res) { * console.log(res); // '4231' * console.log(order); // [4, 2, 3, 1] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, result + num); * }, num * 10); * }; * async.reduceRight(collection, 0, iterator, function(err, res) { * console.log(res); // 10 * console.log(order); // [[4, 3], [2, 2], [3, 1], [1, 0]] * }); * */ 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; iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { resIndex = collection.size; col = Array(resIndex); iter = collection[iteratorSymbol](); index = -1; while ((item = iter.next()).done === false) { col[++index] = item.value; } collection = col; 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; } } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach */ function createTransform(arrayEach, baseEach, symbolEach) { return function transform(collection, accumulator, iterator, callback) { if (arguments.length === 3) { callback = iterator; iterator = accumulator; accumulator = undefined; } callback = callback || noop; var size, keys, result; var completed = 0; if (isArray(collection)) { size = collection.length; result = accumulator !== undefined ? accumulator : []; arrayEach(collection, result, iterator, done); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; result = accumulator !== undefined ? accumulator : {}; symbolEach(collection, result, iterator, done); } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; result = accumulator !== undefined ? accumulator : {}; baseEach(collection, result, iterator, done, keys); } if (!size) { callback(null, accumulator !== undefined ? accumulator : result || {}); } function done(err, bool) { if (err) { callback = once(callback); callback(err, isArray(result) ? createArray(result) : objectClone(result)); } else if (++completed === size) { callback(null, result); } else if (bool === false) { callback = once(callback); callback(null, isArray(result) ? createArray(result) : objectClone(result)); } } }; } /** * @memberof async * @namespace transformSeries * @param {Array|Object} collection * @param {Array|Object|Function} [accumulator] * @param {Function} [iterator] * @param {Function} [callback] * @example * * // array * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * result.push(num) * done(); * }, num * 10); * }; * async.transformSeries(collection, iterator, function(err, res) { * console.log(res); // [1, 3, 2, 4] * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // array with index and accumulator * var order = []; * var collection = [1, 3, 2, 4]; * var iterator = function(result, num, index, done) { * setTimeout(function() { * order.push([num, index]); * result[index] = num; * done(); * }, num * 10); * }; * async.transformSeries(collection, {}, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 3, '2': 2, '3': 4 } * console.log(order); // [[1, 0], [3, 1], [2, 2], [4, 3]] * }); * * @example * * // object with accumulator * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * result.push(num); * done(); * }, num * 10); * }; * async.transformSeries(collection, [], iterator, function(err, res) { * console.log(res); // [1, 3, 2, 4] * console.log(order); // [1, 3, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2, d: 4 }; * var iterator = function(result, num, key, done) { * setTimeout(function() { * order.push([num, key]); * result[key] = num; * done(); * }, num * 10); * }; * async.transformSeries(collection, iterator, function(err, res) { * console.log(res); // { a: 1, b: 3, c: 2, d: 4 } * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'b'], [4, 'd']] * }); * */ function transformSeries(collection, accumulator, iterator, callback) { if (arguments.length === 3) { callback = iterator; iterator = accumulator; accumulator = undefined; } callback = onlyOnce(callback || noop); var size, key, keys, iter, iterate, result; var sync = false; var completed = 0; if (isArray(collection)) { size = collection.length; result = accumulator !== undefined ? accumulator : []; iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); result = accumulator !== undefined ? accumulator : {}; iterate = iterator.length === 4 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; result = accumulator !== undefined ? accumulator : {}; iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, accumulator !== undefined ? accumulator : result || {}); } iterate(); function arrayIterator() { iterator(result, collection[completed], done); } function arrayIteratorWithIndex() { iterator(result, collection[completed], completed, done); } function symbolIterator() { iterator(result, iter.next().value, done); } function symbolIteratorWithKey() { iterator(result, iter.next().value, completed, done); } function objectIterator() { iterator(result, collection[keys[completed]], done); } function objectIteratorWithKey() { key = keys[completed]; iterator(result, collection[key], key, done); } function done(err, bool) { if (err) { callback(err, result); } else if (++completed === size) { iterate = throwError; callback(null, result); } else if (bool === false) { iterate = throwError; callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace transformLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Array|Object|Function} [accumulator] * @param {Function} [iterator] * @param {Function} [callback] * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * result.push(num); * done(); * }, num * 10); * }; * async.transformLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 3, 5, 2, 4] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index and accumulator * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(result, num, index, done) { * setTimeout(function() { * order.push([num, index]); * result[index] = key; * done(); * }, num * 10); * }; * async.transformLimit(array, 2, {}, iterator, function(err, res) { * console.log(res); // { '0': 1, '1': 5, '2': 3, '3': 4, '4': 2 } * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object with accumulator * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(result, num, done) { * setTimeout(function() { * order.push(num); * result.push(num); * done(); * }, num * 10); * }; * async.transformLimit(object, 2, [], iterator, function(err, res) { * console.log(res); // [1, 3, 5, 2, 4] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(result, num, key, done) { * setTimeout(function() { * order.push([num, key]); * result[key] = num; * done(); * }, num * 10); * }; * async.transformLimit(object, 2, iterator, function(err, res) { * console.log(res); // { a: 1, b: 5, c: 3, d: 4, e: 2 }; * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ function transformLimit(collection, limit, accumulator, iterator, callback) { if (arguments.length === 4) { callback = iterator; iterator = accumulator; accumulator = undefined; } callback = callback || noop; var size, index, key, keys, iter, item, iterate, result; var sync = false; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; result = accumulator !== undefined ? accumulator : []; iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); result = accumulator !== undefined ? accumulator : {}; iterate = iterator.length === 4 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; result = accumulator !== undefined ? accumulator : {}; iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, accumulator !== undefined ? accumulator : result || {}); } timesSync(limit > size ? size : limit, iterate); function arrayIterator() { index = started++; if (index < size) { iterator(result, collection[index], onlyOnce(done)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { iterator(result, collection[index], index, onlyOnce(done)); } } function symbolIterator() { if ((item = iter.next()).done === false) { iterator(result, item.value, onlyOnce(done)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { iterator(result, item.value, started++, onlyOnce(done)); } } function objectIterator() { index = started++; if (index < size) { iterator(result, collection[keys[index]], onlyOnce(done)); } } function objectIteratorWithKey() { index = started++; if (index < size) { key = keys[index]; iterator(result, collection[key], key, onlyOnce(done)); } } function done(err, bool) { if (err) { iterate = noop; callback(err, isArray(result) ? createArray(result) : objectClone(result)); callback = noop; } else if (++completed === size) { callback(null, result); } else if (bool === false) { iterate = noop; callback(null, isArray(result) ? createArray(result) : objectClone(result)); callback = noop; } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @private * @param {function} arrayEach * @param {function} baseEach * @param {function} symbolEach */ function createSortBy(arrayEach, baseEach, symbolEach) { return function sortBy(collection, iterator, callback) { callback = callback || noop; var size, array, criteria; var completed = 0; if (isArray(collection)) { size = collection.length; array = Array(size); criteria = Array(size); arrayEach(collection, iterator, createCallback); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; array = Array(size); criteria = Array(size); symbolEach(collection, iterator, createCallback); } else if (typeof collection === obj) { var keys = nativeKeys(collection); size = keys.length; array = Array(size); criteria = Array(size); baseEach(collection, iterator, createCallback, keys); } if (!size) { callback(null, []); } function createCallback(index, value) { var called = false; array[index] = value; return function done(err, criterion) { if (called) { throwError(); } called = true; criteria[index] = criterion; if (err) { callback = once(callback); callback(err); } else if (++completed === size) { callback(null, sortByCriteria(array, criteria)); } }; } }; } /** * @memberof async * @namespace sortBySeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.sortBySeries(array, iterator, function(err, res) { * console.log(res); // [1, 2, 3]; * console.log(order); // [1, 3, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.sortBySeries(array, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [[1, 0], [3, 1], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.sortBySeries(object, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.sortBySeries(object, iterator, function(err, res) { * console.log(res); // [1, 2, 3] * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']] * }); * */ function sortBySeries(collection, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, value, keys, iter, array, criteria, iterate; var sync = false; var completed = 0; if (isArray(collection)) { size = collection.length; array = collection; criteria = Array(size); iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; array = Array(size); criteria = Array(size); iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; array = Array(size); criteria = Array(size); iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, []); } iterate(); function arrayIterator() { value = collection[completed]; iterator(value, done); } function arrayIteratorWithIndex() { value = collection[completed]; iterator(value, completed, done); } function symbolIterator() { value = iter.next().value; array[completed] = value; iterator(value, done); } function symbolIteratorWithKey() { value = iter.next().value; array[completed] = value; iterator(value, completed, done); } function objectIterator() { value = collection[keys[completed]]; array[completed] = value; iterator(value, done); } function objectIteratorWithKey() { key = keys[completed]; value = collection[key]; array[completed] = value; iterator(value, key, done); } function done(err, criterion) { criteria[completed] = criterion; if (err) { callback(err); } else if (++completed === size) { iterate = throwError; callback(null, sortByCriteria(array, criteria)); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace sortByLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.sortByLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 2, 3, 4, 5] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num); * }, num * 10); * }; * async.sortByLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 2, 3, 4, 5] * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num); * }, num * 10); * }; * async.sortByLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 2, 3, 4, 5] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.sortByLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 2, 3, 4, 5] * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ function sortByLimit(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, value, array, keys, iter, item, criteria, iterate; var sync = false; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; array = collection; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); array = Array(size); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; array = Array(size); iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, []); } criteria = Array(size); timesSync(limit > size ? size : limit, iterate); function arrayIterator() { if (started < size) { value = collection[started]; iterator(value, createCallback(value, started++)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { value = collection[index]; iterator(value, index, createCallback(value, index)); } } function symbolIterator() { if ((item = iter.next()).done === false) { value = item.value; array[started] = value; iterator(value, createCallback(value, started++)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { value = item.value; array[started] = value; iterator(value, started, createCallback(value, started++)); } } function objectIterator() { if (started < size) { value = collection[keys[started]]; array[started] = value; iterator(value, createCallback(value, started++)); } } function objectIteratorWithKey() { if (started < size) { key = keys[started]; value = collection[key]; array[started] = value; iterator(value, key, createCallback(value, started++)); } } function createCallback(value, index) { var called = false; return function(err, criterion) { if (called) { throwError(); } called = true; criteria[index] = criterion; if (err) { iterate = noop; callback(err); callback = noop; } else if (++completed === size) { callback(null, sortByCriteria(array, criteria)); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } } /** * @memberof async * @namespace some * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.some(array, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [1] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.some(array, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [[1, 0]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.some(object, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [1] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.some(object, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [[1, 'a']] * }); * */ function some(collection, iterator, callback) { callback = callback || noop; detect(collection, iterator, done); function done(err, res) { if (err) { return callback(err); } callback(null, !!res); } } /** * @memberof async * @namespace someSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.someSeries(array, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [1] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.someSeries(array, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [[1, 0]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.someSeries(object, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [1] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.someSeries(object, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [[1, 'a']] * }); * */ function someSeries(collection, iterator, callback) { callback = callback || noop; detectSeries(collection, iterator, done); function done(err, res) { if (err) { return callback(err); } callback(null, !!res); } } /** * @memberof async * @namespace someLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.someLimit(array, 2, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [1] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, num % 2); * }, num * 10); * }; * async.someLimit(array, 2, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [[1, 0]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, num % 2); * }, num * 10); * }; * async.someLimit(object, 2, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [1] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num % 2); * }, num * 10); * }; * async.someLimit(object, 2, iterator, function(err, res) { * console.log(res); // true * console.log(order); // [[1, 'a']] * }); * */ function someLimit(collection, limit, iterator, callback) { callback = callback || noop; detectLimit(collection, limit, iterator, done); function done(err, res) { if (err) { return callback(err); } callback(null, !!res); } } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach */ function createEvery(arrayEach, baseEach, symbolEach) { var deny = createDetect(arrayEach, baseEach, symbolEach, false); return function every(collection, iterator, callback) { callback = callback || noop; deny(collection, iterator, done); function done(err, res) { if (err) { return callback(err); } callback(null, !res); } }; } /** * @private */ function createEverySeries() { var denySeries = createDetectSeries(false); return function everySeries(collection, iterator, callback) { callback = callback || noop; denySeries(collection, iterator, done); function done(err, res) { if (err) { return callback(err); } callback(null, !res); } }; } /** * @private */ function createEveryLimit() { var denyLimit = createDetectLimit(false); return function everyLimit(collection, limit, iterator, callback) { callback = callback || noop; denyLimit(collection, limit, iterator, done); function done(err, res) { if (err) { return callback(err); } callback(null, !res); } }; } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach */ function createConcat(arrayEach, baseEach, symbolEach) { return function concat(collection, iterator, callback) { callback = callback || noop; var size, result; var completed = 0; if (isArray(collection)) { size = collection.length; result = Array(size); arrayEach(collection, iterator, createCallback); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; result = Array(size); symbolEach(collection, iterator, createCallback); } else if (typeof collection === obj) { var keys = nativeKeys(collection); size = keys.length; result = Array(size); baseEach(collection, iterator, createCallback, keys); } if (!size) { callback(null, []); } function createCallback(index) { return function done(err, res) { if (index === null) { throwError(); } if (err) { index = null; callback = once(callback); arrayEachSync(result, function(array, index) { if (array === undefined) { result[index] = noop; } }); callback(err, makeConcatResult(result)); return; } switch (arguments.length) { case 0: case 1: result[index] = noop; break; case 2: result[index] = res; break; default: result[index] = slice(arguments, 1); break; } index = null; if (++completed === size) { callback(null, makeConcatResult(result)); } }; } }; } /** * @memberof async * @namespace concatSeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, [num]); * }, num * 10); * }; * async.concatSeries(array, iterator, function(err, res) { * console.log(res); // [1, 3, 2]; * console.log(order); // [1, 3, 2] * }); * * @example * * // array with index * var order = []; * var array = [1, 3, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, [num]); * }, num * 10); * }; * async.concatSeries(array, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [[1, 0], [3, 1], [2, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, [num]); * }, num * 10); * }; * async.concatSeries(object, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [1, 3, 2] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 3, c: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, [num]); * }, num * 10); * }; * async.concatSeries(object, iterator, function(err, res) { * console.log(res); // [1, 3, 2] * console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']] * }); * */ function concatSeries(collection, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, keys, iter, values, iterate; var sync = false; var result = []; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, result); } iterate(); function arrayIterator() { iterator(collection[completed], done); } function arrayIteratorWithIndex() { iterator(collection[completed], completed, done); } function symbolIterator() { iterator(iter.next().value, done); } function symbolIteratorWithKey() { values = iter.next().value; iterator(values, completed, done); } function objectIterator() { iterator(collection[keys[completed]], done); } function objectIteratorWithKey() { key = keys[completed]; iterator(collection[key], key, done); } function done(err, array) { if (isArray(array)) { nativePush.apply(result, array); } else if (arguments.length >= 2) { nativePush.apply(result, slice(arguments, 1)); } if (err) { callback(err, result); } else if (++completed === size) { iterate = throwError; callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace concatLimit * @param {Array|Object} collection * @param {number} limit - limit >= 1 * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, [num]); * }, num * 10); * }; * async.concatLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 3, 5, 2, 4] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // array with index * var order = []; * var array = [1, 5, 3, 4, 2]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, [num]); * }, num * 10); * }; * async.cocnatLimit(array, 2, iterator, function(err, res) { * console.log(res); // [1, 3, 5, 2, 4] * console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, [num]); * }, num * 10); * }; * async.concatLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 3, 5, 2, 4] * console.log(order); // [1, 3, 5, 2, 4] * }); * * @example * * // object with key * var order = []; * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, num); * }, num * 10); * }; * async.cocnatLimit(object, 2, iterator, function(err, res) { * console.log(res); // [1, 3, 5, 2, 4] * console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']] * }); * */ function concatLimit(collection, limit, iterator, callback) { callback = callback || noop; var size, key, iter, item, iterate; var sync = false; var started = 0; var completed = 0; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { var keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, []); } var result = Array(size); timesSync(limit > size ? size : limit, iterate); function arrayIterator() { if (started < size) { iterator(collection[started], createCallback(started++)); } } function arrayIteratorWithIndex() { if (started < size) { iterator(collection[started], started, createCallback(started++)); } } function symbolIterator() { if ((item = iter.next()).done === false) { iterator(item.value, createCallback(started++)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { iterator(item.value, started, createCallback(started++)); } } function objectIterator() { if (started < size) { iterator(collection[keys[started]], createCallback(started++)); } } function objectIteratorWithKey() { if (started < size) { key = keys[started]; iterator(collection[key], key, createCallback(started++)); } } function createCallback(index) { return function(err, res) { if (index === null) { throwError(); } if (err) { index = null; iterate = noop; callback = once(callback); arrayEachSync(result, function(array, index) { if (array === undefined) { result[index] = noop; } }); callback(err, makeConcatResult(result)); return; } switch (arguments.length) { case 0: case 1: result[index] = noop; break; case 2: result[index] = res; break; default: result[index] = slice(arguments, 1); break; } index = null; if (++completed === size) { iterate = throwError; callback(null, makeConcatResult(result)); callback = throwError; } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } } /** * @private * @param {Function} arrayEach * @param {Function} baseEach * @param {Function} symbolEach */ function createGroupBy(arrayEach, baseEach, symbolEach) { return function groupBy(collection, iterator, callback) { callback = callback || noop; var size; var completed = 0; var result = {}; if (isArray(collection)) { size = collection.length; arrayEach(collection, iterator, createCallback); } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; symbolEach(collection, iterator, createCallback); } else if (typeof collection === obj) { var keys = nativeKeys(collection); size = keys.length; baseEach(collection, iterator, createCallback, keys); } if (!size) { callback(null, {}); } function createCallback(value) { var called = false; return function done(err, key) { if (called) { throwError(); } called = true; if (err) { callback = once(callback); callback(err, objectClone(result)); return; } var array = result[key]; if (!array) { array = result[key] = [value]; } else { array.push(value); } if (++completed === size) { callback(null, result); } }; } }; } /** * @memberof async * @namespace groupBySeries * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [4.2, 6.4, 6.1]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBySeries(array, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.4, 6.1] } * console.log(order); // [4.2, 6.4, 6.1] * }); * * @example * * // array with index * var order = []; * var array = [4.2, 6.4, 6.1]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBySeries(array, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.4, 6.1] } * console.log(order); // [[4.2, 0], [6.4, 1], [6.1, 2]] * }); * * @example * * // object * var order = []; * var object = { a: 4.2, b: 6.4, c: 6.1 }; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBySeries(object, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.4, 6.1] } * console.log(order); // [4.2, 6.4, 6.1] * }); * * @example * * // object with key * var order = []; * var object = { a: 4.2, b: 6.4, c: 6.1 }; * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupBySeries(object, iterator, function(err, res) { * console.log(res); // { '4': [4.2], '6': [6.4, 6.1] } * console.log(order); // [[4.2, 'a'], [6.4, 'b'], [6.1, 'c']] * }); * */ function groupBySeries(collection, iterator, callback) { callback = onlyOnce(callback || noop); var size, key, value, keys, iter, iterate; var sync = false; var completed = 0; var result = {}; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size) { return callback(null, result); } iterate(); function arrayIterator() { value = collection[completed]; iterator(value, done); } function arrayIteratorWithIndex() { value = collection[completed]; iterator(value, completed, done); } function symbolIterator() { value = iter.next().value; iterator(value, done); } function symbolIteratorWithKey() { value = iter.next().value; iterator(value, completed, done); } function objectIterator() { value = collection[keys[completed]]; iterator(value, done); } function objectIteratorWithKey() { key = keys[completed]; value = collection[key]; iterator(value, key, done); } function done(err, key) { if (err) { iterate = throwError; callback = onlyOnce(callback); callback(err, objectClone(result)); return; } var array = result[key]; if (!array) { array = result[key] = [value]; } else { array.push(value); } if (++completed === size) { iterate = throwError; callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace groupByLimit * @param {Array|Object} collection * @param {Function} iterator * @param {Function} callback * @example * * // array * var order = []; * var array = [1.1, 5.9, 3.2, 3.9, 2.1]; * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupByLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] } * console.log(order); // [1.1, 3.2, 5.9, 2.1, 3.9] * }); * * @example * * // array with index * var order = []; * var array = [1.1, 5.9, 3.2, 3.9, 2.1]; * var iterator = function(num, index, done) { * setTimeout(function() { * order.push([num, index]); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupByLimit(array, 2, iterator, function(err, res) { * console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] } * console.log(order); // [[1.1, 0], [3.2, 2], [5.9, 1], [2.1, 4], [3.9, 3]] * }); * * @example * * // object * var order = []; * var object = { a: 1.1, b: 5.9, c: 3.2, d: 3.9, e: 2.1 } * var iterator = function(num, done) { * setTimeout(function() { * order.push(num); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupByLimit(object, 2, iterator, function(err, res) { * console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] } * console.log(order); // [1.1, 3.2, 5.9, 2.1, 3.9] * }); * * @example * * // object with key * var order = []; * var object = { a: 1.1, b: 5.9, c: 3.2, d: 3.9, e: 2.1 } * var iterator = function(num, key, done) { * setTimeout(function() { * order.push([num, key]); * done(null, Math.floor(num)); * }, num * 10); * }; * async.groupByLimit(object, 2, iterator, function(err, res) { * console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] } * console.log(order); // [[1.1, 'a'], [3.2, 'c'], [5.9, 'b'], [2.1, 'e'], [3.9, 'd']] * }); * */ function groupByLimit(collection, limit, iterator, callback) { callback = callback || noop; var size, index, key, value, keys, iter, item, iterate; var sync = false; var started = 0; var completed = 0; var result = {}; if (isArray(collection)) { size = collection.length; iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator; } else if (!collection) { } else if (iteratorSymbol && collection[iteratorSymbol]) { size = collection.size; iter = collection[iteratorSymbol](); iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator; } else if (typeof collection === obj) { keys = nativeKeys(collection); size = keys.length; iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, result); } timesSync(limit > size ? size : limit, iterate); function arrayIterator() { if (started < size) { value = collection[started++]; iterator(value, createCallback(value)); } } function arrayIteratorWithIndex() { index = started++; if (index < size) { value = collection[index]; iterator(value, index, createCallback(value)); } } function symbolIterator() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, createCallback(value)); } } function symbolIteratorWithKey() { if ((item = iter.next()).done === false) { value = item.value; iterator(value, started++, createCallback(value)); } } function objectIterator() { if (started < size) { value = collection[keys[started++]]; iterator(value, createCallback(value)); } } function objectIteratorWithKey() { if (started < size) { key = keys[started++]; value = collection[key]; iterator(value, key, createCallback(value)); } } function createCallback(value) { var called = false; return function(err, key) { if (called) { throwError(); } called = true; if (err) { iterate = noop; callback = once(callback); callback(err, objectClone(result)); return; } var array = result[key]; if (!array) { result[key] = [value]; } else { array.push(value); } if (++completed === size) { callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } } /** * @private * @param {Function} arrayEach * @param {Function} baseEach */ function createParallel(arrayEach, baseEach) { return function parallel(tasks, callback) { callback = callback || noop; var size, keys, result; var completed = 0; if (isArray(tasks)) { size = tasks.length; result = Array(size); arrayEach(tasks, createCallback); } else if (tasks && typeof tasks === obj) { keys = nativeKeys(tasks); size = keys.length; result = {}; baseEach(tasks, createCallback, keys); } if (!size) { callback(null, result); } function createCallback(key) { return function(err, res) { if (key === null) { throwError(); } if (err) { key = null; callback = once(callback); callback(err, result); return; } result[key] = arguments.length <= 2 ? res : slice(arguments, 1); key = null; if (++completed === size) { callback(null, result); } }; } }; } /** * @memberof async * @namespace series * @param {Array|Object} tasks - functions * @param {Function} callback * @example * * var order = []; * var tasks = [ * function(done) { * setTimeout(function() { * order.push(1); * done(null, 1); * }, 10); * }, * function(done) { * setTimeout(function() { * order.push(2); * done(null, 2); * }, 30); * }, * function(done) { * setTimeout(function() { * order.push(3); * done(null, 3); * }, 40); * }, * function(done) { * setTimeout(function() { * order.push(4); * done(null, 4); * }, 20); * } * ]; * async.series(tasks, function(err, res) { * console.log(res); // [1, 2, 3, 4]; * console.log(order); // [1, 2, 3, 4] * }); * * @example * * var order = []; * var tasks = { * 'a': function(done) { * setTimeout(function() { * order.push(1); * done(null, 1); * }, 10); * }, * 'b': function(done) { * setTimeout(function() { * order.push(2); * done(null, 2); * }, 30); * }, * 'c': function(done) { * setTimeout(function() { * order.push(3); * done(null, 3); * }, 40); * }, * 'd': function(done) { * setTimeout(function() { * order.push(4); * done(null, 4); * }, 20); * } * }; * async.series(tasks, function(err, res) { * console.log(res); // { a: 1, b: 2, c: 3, d:4 } * console.log(order); // [1, 4, 2, 3] * }); * */ function series(tasks, callback) { callback = callback || noop; var size, key, keys, result, iterate; var sync = false; var completed = 0; if (isArray(tasks)) { size = tasks.length; result = Array(size); iterate = arrayIterator; } else if (tasks && typeof tasks === obj) { keys = nativeKeys(tasks); size = keys.length; result = {}; iterate = objectIterator; } else { return callback(null); } if (!size) { return callback(null, result); } iterate(); function arrayIterator() { key = completed; tasks[completed](done); } function objectIterator() { key = keys[completed]; tasks[key](done); } function done(err, res) { if (err) { iterate = throwError; callback = onlyOnce(callback); callback(err, result); return; } result[key] = arguments.length <= 2 ? res : slice(arguments, 1); if (++completed === size) { iterate = throwError; callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace parallelLimit * @param {Array|Object} tasks - functions * @param {number} limit - limit >= 1 * @param {Function} callback * @example * * var order = []; * var tasks = [ * function(done) { * setTimeout(function() { * order.push(1); * done(null, 1); * }, 10); * }, * function(done) { * setTimeout(function() { * order.push(2); * done(null, 2); * }, 50); * }, * function(done) { * setTimeout(function() { * order.push(3); * done(null, 3); * }, 30); * }, * function(done) { * setTimeout(function() { * order.push(4); * done(null, 4); * }, 40); * } * ]; * async.parallelLimit(tasks, 2, function(err, res) { * console.log(res); // [1, 2, 3, 4]; * console.log(order); // [1, 3, 2, 4] * }); * * @example * * var order = []; * var tasks = { * 'a': function(done) { * setTimeout(function() { * order.push(1); * done(null, 1); * }, 10); * }, * 'b': function(done) { * setTimeout(function() { * order.push(2); * done(null, 2); * }, 50); * }, * 'c': function(done) { * setTimeout(function() { * order.push(3); * done(null, 3); * }, 20); * }, * 'd': function(done) { * setTimeout(function() { * order.push(4); * done(null, 4); * }, 40); * } * }; * async.parallelLimit(tasks, 2, function(err, res) { * console.log(res); // { a: 1, b: 2, c: 3, d:4 } * console.log(order); // [1, 3, 2, 4] * }); * */ function parallelLimit(tasks, limit, callback) { callback = callback || noop; var size, index, key, keys, result, iterate; var sync = false; var started = 0; var completed = 0; if (isArray(tasks)) { size = tasks.length; result = Array(size); iterate = arrayIterator; } else if (tasks && typeof tasks === obj) { keys = nativeKeys(tasks); size = keys.length; result = {}; iterate = objectIterator; } if (!size || isNaN(limit) || limit < 1) { return callback(null, result); } timesSync(limit > size ? size : limit, iterate); function arrayIterator() { index = started++; if (index < size) { tasks[index](createCallback(index)); } } function objectIterator() { if (started < size) { key = keys[started++]; tasks[key](createCallback(key)); } } function createCallback(key) { return function(err, res) { if (key === null) { throwError(); } if (err) { key = null; iterate = noop; callback = once(callback); callback(err, result); return; } result[key] = arguments.length <= 2 ? res : slice(arguments, 1); key = null; if (++completed === size) { callback(null, result); } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } } /** * @memberof async * @namespace tryEach * @param {Array|Object} tasks - functions * @param {Function} callback * @example * * var tasks = [ * function(done) { * setTimeout(function() { * done(new Error('error')); * }, 10); * }, * function(done) { * setTimeout(function() { * done(null, 2); * }, 10); * } * ]; * async.tryEach(tasks, function(err, res) { * console.log(res); // 2 * }); * * @example * * var tasks = [ * function(done) { * setTimeout(function() { * done(new Error('error1')); * }, 10); * }, * function(done) { * setTimeout(function() { * done(new Error('error2'); * }, 10); * } * ]; * async.tryEach(tasks, function(err, res) { * console.log(err); // error2 * console.log(res); // undefined * }); * */ function tryEach(tasks, callback) { callback = callback || noop; var size, keys, iterate; var sync = false; var completed = 0; if (isArray(tasks)) { size = tasks.length; iterate = arrayIterator; } else if (tasks && typeof tasks === obj) { keys = nativeKeys(tasks); size = keys.length; iterate = objectIterator; } if (!size) { return callback(null); } iterate(); function arrayIterator() { tasks[completed](done); } function objectIterator() { tasks[keys[completed]](done); } function done(err, res) { if (!err) { if (arguments.length <= 2) { callback(null, res); } else { callback(null, slice(arguments, 1)); } } else if (++completed === size) { callback(err); } else { sync = true; iterate(); } sync = false; } } /** * check for waterfall tasks * @private * @param {Array} tasks * @param {Function} callback * @return {boolean} */ function checkWaterfallTasks(tasks, callback) { if (!isArray(tasks)) { callback(new Error('First argument to waterfall must be an array of functions')); return false; } if (tasks.length === 0) { callback(null); return false; } return true; } /** * check for waterfall tasks * @private * @param {function} func * @param {Array|Object} args - arguments * @return {function} next */ function waterfallIterator(func, args, next) { switch (args.length) { case 0: case 1: return func(next); case 2: return func(args[1], next); case 3: return func(args[1], args[2], next); case 4: return func(args[1], args[2], args[3], next); case 5: return func(args[1], args[2], args[3], args[4], next); case 6: return func(args[1], args[2], args[3], args[4], args[5], next); default: args = slice(args, 1); args.push(next); return func.apply(null, args); } } /** * @memberof async * @namespace waterfall * @param {Array} tasks - functions * @param {Function} callback * @example * * var order = []; * var tasks = [ * function(next) { * setTimeout(function() { * order.push(1); * next(null, 1); * }, 10); * }, * function(arg1, next) { * setTimeout(function() { * order.push(2); * next(null, 1, 2); * }, 30); * }, * function(arg1, arg2, next) { * setTimeout(function() { * order.push(3); * next(null, 3); * }, 20); * }, * function(arg1, next) { * setTimeout(function() { * order.push(4); * next(null, 1, 2, 3, 4); * }, 40); * } * ]; * async.waterfall(tasks, function(err, arg1, arg2, arg3, arg4) { * console.log(arg1, arg2, arg3, arg4); // 1 2 3 4 * }); * */ function waterfall(tasks, callback) { callback = callback || noop; if (!checkWaterfallTasks(tasks, callback)) { return; } var func, args, done, sync; var completed = 0; var size = tasks.length; waterfallIterator(tasks[0], [], createCallback(0)); function iterate() { waterfallIterator(func, args, createCallback(func)); } function createCallback(index) { return function next(err, res) { if (index === undefined) { callback = noop; throwError(); } index = undefined; if (err) { done = callback; callback = throwError; done(err); return; } if (++completed === size) { done = callback; callback = throwError; if (arguments.length <= 2) { done(err, res); } else { done.apply(null, createArray(arguments)); } return; } if (sync) { args = arguments; func = tasks[completed] || throwError; nextTick(iterate); } else { sync = true; waterfallIterator(tasks[completed] || throwError, arguments, createCallback(completed)); } sync = false; }; } } /** * `angelFall` is like `waterfall` and inject callback to last argument of next task. * * @memberof async * @namespace angelFall * @param {Array} tasks - functions * @param {Function} callback * @example * * var order = []; * var tasks = [ * function(next) { * setTimeout(function() { * order.push(1); * next(null, 1); * }, 10); * }, * function(arg1, empty, next) { * setTimeout(function() { * order.push(2); * next(null, 1, 2); * }, 30); * }, * function(next) { * setTimeout(function() { * order.push(3); * next(null, 3); * }, 20); * }, * function(arg1, empty1, empty2, empty3, next) { * setTimeout(function() { * order.push(4); * next(null, 1, 2, 3, 4); * }, 40); * } * ]; * async.angelFall(tasks, function(err, arg1, arg2, arg3, arg4) { * console.log(arg1, arg2, arg3, arg4); // 1 2 3 4 * }); * */ function angelFall(tasks, callback) { callback = callback || noop; if (!checkWaterfallTasks(tasks, callback)) { return; } var completed = 0; var sync = false; var size = tasks.length; var func = tasks[completed]; var args = []; var iterate = function() { switch (func.length) { case 0: try { next(null, func()); } catch (e) { next(e); } return; case 1: return func(next); case 2: return func(args[1], next); case 3: return func(args[1], args[2], next); case 4: return func(args[1], args[2], args[3], next); case 5: return func(args[1], args[2], args[3], args[4], next); default: args = slice(args, 1); args[func.length - 1] = next; return func.apply(null, args); } }; iterate(); function next(err, res) { if (err) { iterate = throwError; callback = onlyOnce(callback); callback(err); return; } if (++completed === size) { iterate = throwError; var done = callback; callback = throwError; if (arguments.length === 2) { done(err, res); } else { done.apply(null, createArray(arguments)); } return; } func = tasks[completed]; args = arguments; if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace whilst * @param {Function} test * @param {Function} iterator * @param {Function} callback */ function whilst(test, iterator, callback) { callback = callback || noop; var sync = false; if (test()) { iterate(); } else { callback(null); } function iterate() { if (sync) { nextTick(next); } else { sync = true; iterator(done); } sync = false; } function next() { iterator(done); } function done(err, arg) { if (err) { return callback(err); } if (arguments.length <= 2) { if (test(arg)) { iterate(); } else { callback(null, arg); } return; } arg = slice(arguments, 1); if (test.apply(null, arg)) { iterate(); } else { callback.apply(null, [null].concat(arg)); } } } /** * @memberof async * @namespace doWhilst * @param {Function} iterator * @param {Function} test * @param {Function} callback */ function doWhilst(iterator, test, callback) { callback = callback || noop; var sync = false; next(); function iterate() { if (sync) { nextTick(next); } else { sync = true; iterator(done); } sync = false; } function next() { iterator(done); } function done(err, arg) { if (err) { return callback(err); } if (arguments.length <= 2) { if (test(arg)) { iterate(); } else { callback(null, arg); } return; } arg = slice(arguments, 1); if (test.apply(null, arg)) { iterate(); } else { callback.apply(null, [null].concat(arg)); } } } /** * @memberof async * @namespace until * @param {Function} test * @param {Function} iterator * @param {Function} callback */ function until(test, iterator, callback) { callback = callback || noop; var sync = false; if (!test()) { iterate(); } else { callback(null); } function iterate() { if (sync) { nextTick(next); } else { sync = true; iterator(done); } sync = false; } function next() { iterator(done); } function done(err, arg) { if (err) { return callback(err); } if (arguments.length <= 2) { if (!test(arg)) { iterate(); } else { callback(null, arg); } return; } arg = slice(arguments, 1); if (!test.apply(null, arg)) { iterate(); } else { callback.apply(null, [null].concat(arg)); } } } /** * @memberof async * @namespace doUntil * @param {Function} iterator * @param {Function} test * @param {Function} callback */ function doUntil(iterator, test, callback) { callback = callback || noop; var sync = false; next(); function iterate() { if (sync) { nextTick(next); } else { sync = true; iterator(done); } sync = false; } function next() { iterator(done); } function done(err, arg) { if (err) { return callback(err); } if (arguments.length <= 2) { if (!test(arg)) { iterate(); } else { callback(null, arg); } return; } arg = slice(arguments, 1); if (!test.apply(null, arg)) { iterate(); } else { callback.apply(null, [null].concat(arg)); } } } /** * @memberof async * @namespace during * @param {Function} test * @param {Function} iterator * @param {Function} callback */ function during(test, iterator, callback) { callback = callback || noop; _test(); function _test() { test(iterate); } function iterate(err, truth) { if (err) { return callback(err); } if (truth) { iterator(done); } else { callback(null); } } function done(err) { if (err) { return callback(err); } _test(); } } /** * @memberof async * @namespace doDuring * @param {Function} test * @param {Function} iterator * @param {Function} callback */ function doDuring(iterator, test, callback) { callback = callback || noop; iterate(null, true); function iterate(err, truth) { if (err) { return callback(err); } if (truth) { iterator(done); } else { callback(null); } } function done(err, res) { if (err) { return callback(err); } switch (arguments.length) { case 0: case 1: test(iterate); break; case 2: test(res, iterate); break; default: var args = slice(arguments, 1); args.push(iterate); test.apply(null, args); break; } } } /** * @memberof async * @namespace forever */ function forever(iterator, callback) { var sync = false; iterate(); function iterate() { iterator(next); } function next(err) { if (err) { if (callback) { return callback(err); } throw err; } if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace compose */ function compose() { return seq.apply(null, reverse(arguments)); } /** * @memberof async * @namespace seq */ function seq( /* functions... */ ) { var fns = createArray(arguments); return function() { var self = this; 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) { var func = function(err) { var nextargs = slice(arguments, 1); callback(err, nextargs); }; newargs.push(func); fn.apply(self, newargs); } function done(err, res) { res = isArray(res) ? res : [res]; res.unshift(err); callback.apply(self, res); } }; } function createApplyEach(func) { return function applyEach(fns /* arguments */ ) { var go = function() { var self = this; var args = createArray(arguments); var callback = args.pop() || noop; return func(fns, iterator, callback); function iterator(fn, done) { fn.apply(self, args.concat([done])); } }; if (arguments.length > 1) { var args = slice(arguments, 1); return go.apply(this, args); } else { return go; } }; } /** * @see https://github.com/caolan/async/blob/master/lib/internal/DoublyLinkedList.js */ function DLL() { this.head = null; this.tail = null; this.length = 0; } DLL.prototype._removeLink = function(node) { var prev = node.prev; var next = node.next; if (prev) { prev.next = next; } else { this.head = next; } if (next) { next.prev = prev; } else { this.tail = prev; } node.prev = null; node.next = null; this.length--; return node; }; DLL.prototype.empty = DLL; DLL.prototype._setInitial = function(node) { this.length = 1; this.head = this.tail = node; }; DLL.prototype.insertBefore = function(node, newNode) { newNode.prev = node.prev; newNode.next = node; if (node.prev) { node.prev.next = newNode; } else { this.head = newNode; } node.prev = newNode; this.length++; }; DLL.prototype.unshift = function(node) { if (this.head) { this.insertBefore(this.head, node); } else { this._setInitial(node); } }; DLL.prototype.push = function(node) { var tail = this.tail; if (tail) { node.prev = tail; node.next = tail.next; this.tail = node; tail.next = node; this.length++; } else { this._setInitial(node); } }; DLL.prototype.shift = function() { return this.head && this._removeLink(this.head); }; DLL.prototype.splice = function(end) { var task; var tasks = []; while (end-- && (task = this.shift())) { tasks.push(task); } return tasks; }; DLL.prototype.remove = function(test) { var node = this.head; while(node) { if (test(node)) { this._removeLink(node); } node = node.next; } return this; }; /** * @private */ function baseQueue(isQueue, worker, concurrency, payload) { if (concurrency === undefined) { concurrency = 1; } else if (isNaN(concurrency) || concurrency < 1) { throw new Error('Concurrency must not be zero'); } var workers = 0; var workersList = []; var _callback, _unshift; var q = { _tasks: new DLL(), concurrency: concurrency, payload: payload, saturated: noop, unsaturated: noop, buffer: concurrency / 4, empty: noop, drain: noop, error: noop, started: false, paused: false, push: push, kill: kill, unshift: unshift, remove: remove, process: isQueue ? runQueue : runCargo, length: getLength, running: running, workersList: getWorkersList, idle: idle, pause: pause, resume: resume, _worker: worker }; return q; function push(tasks, callback) { _insert(tasks, callback); } function unshift(tasks, callback) { _insert(tasks, callback, true); } function _exec(task) { var item = { data: task, callback: _callback }; if (_unshift) { q._tasks.unshift(item); } else { q._tasks.push(item); } nextTick(q.process); } function _insert(tasks, callback, unshift) { if (callback == null) { callback = noop; } else if (typeof callback !== 'function') { throw new Error('task callback must be a function'); } q.started = true; var _tasks = isArray(tasks) ? tasks : [tasks]; if (tasks === undefined || !_tasks.length) { if (q.idle()) { nextTick(q.drain); } return; } _unshift = unshift; _callback = callback; arrayEachSync(_tasks, _exec); } function kill() { q.drain = noop; q._tasks.empty(); } function _next(q, tasks) { var called = false; return function done(err, res) { if (called) { throwError(); } called = true; workers--; var task; var index = -1; var size = workersList.length; var taskIndex = -1; var taskSize = tasks.length; var useApply = arguments.length > 2; var args = useApply && createArray(arguments); while (++taskIndex < taskSize) { task = tasks[taskIndex]; while (++index < size) { if (workersList[index] === task) { workersList.splice(index, 1); index = size; size--; } } index = -1; if (useApply) { task.callback.apply(task, args); } else { task.callback(err, res); } if (err) { q.error(err, task.data); } } if (workers <= q.concurrency - q.buffer) { q.unsaturated(); } if (q._tasks.length + workers === 0) { q.drain(); } q.process(); }; } function runQueue() { while (!q.paused && workers < q.concurrency && q._tasks.length) { var task = q._tasks.shift(); workers++; workersList.push(task); if (q._tasks.length === 0) { q.empty(); } if (workers === q.concurrency) { q.saturated(); } var done = _next(q, [task]); worker(task.data, done); } } function runCargo() { while (!q.paused && workers < q.concurrency && q._tasks.length) { var tasks = q._tasks.splice(q.payload || q._tasks.length); var index = -1; var size = tasks.length; var data = Array(size); while (++index < size) { data[index] = tasks[index].data; } workers++; nativePush.apply(workersList, tasks); if (q._tasks.length === 0) { q.empty(); } if (workers === q.concurrency) { q.saturated(); } var done = _next(q, tasks); worker(data, done); } } function getLength() { return q._tasks.length; } function running() { return workers; } function getWorkersList() { return workersList; } function idle() { return q.length() + workers === 0; } function pause() { q.paused = true; } function _resume() { nextTick(q.process); } function resume() { if (q.paused === false) { return; } q.paused = false; var count = q.concurrency < q._tasks.length ? q.concurrency : q._tasks.length; timesSync(count, _resume); } /** * @param {Function} test */ function remove(test) { q._tasks.remove(test); } } /** * @memberof async * @namespace queue */ function queue(worker, concurrency) { return baseQueue(true, worker, concurrency); } /** * @memberof async * @namespace priorityQueue */ function priorityQueue(worker, concurrency) { var q = baseQueue(true, worker, concurrency); q.push = push; delete q.unshift; return q; function push(tasks, priority, callback) { q.started = true; priority = priority || 0; var _tasks = isArray(tasks) ? tasks : [tasks]; var taskSize = _tasks.length; if (tasks === undefined || taskSize === 0) { if (q.idle()) { nextTick(q.drain); } return; } callback = typeof callback === func ? callback : noop; var nextNode = q._tasks.head; while (nextNode && priority >= nextNode.priority) { nextNode = nextNode.next; } while (taskSize--) { var item = { data: _tasks[taskSize], priority: priority, callback: callback }; if (nextNode) { q._tasks.insertBefore(nextNode, item); } else { q._tasks.push(item); } nextTick(q.process); } } } /** * @memberof async * @namespace cargo */ function cargo(worker, payload) { return baseQueue(false, worker, 1, payload); } /** * @memberof async * @namespace auto * @param {Object} tasks * @param {number} [concurrency] * @param {Function} [callback] */ function auto(tasks, concurrency, callback) { if (typeof concurrency === func) { callback = concurrency; concurrency = null; } var keys = nativeKeys(tasks); var rest = keys.length; var results = {}; if (rest === 0) { return callback(null, results); } var runningTasks = 0; var readyTasks = []; var listeners = Object.create(null); callback = onlyOnce(callback || noop); concurrency = concurrency || rest; baseEachSync(tasks, iterator, keys); proceedQueue(); function iterator(task, key) { // no dependencies var _task, _taskSize; if (!isArray(task)) { _task = task; _taskSize = 0; readyTasks.push([_task, _taskSize, done]); return; } var dependencySize = task.length - 1; _task = task[dependencySize]; _taskSize = dependencySize; if (dependencySize === 0) { readyTasks.push([_task, _taskSize, done]); return; } // dependencies var index = -1; while (++index < dependencySize) { var dependencyName = task[index]; if (notInclude(keys, dependencyName)) { var msg = 'async.auto task `' + key + '` has non-existent dependency `' + dependencyName + '` in ' + task.join(', '); throw new Error(msg); } var taskListeners = listeners[dependencyName]; if (!taskListeners) { taskListeners = listeners[dependencyName] = []; } taskListeners.push(taskListener); } function done(err, arg) { if (key === null) { throwError(); } arg = arguments.length <= 2 ? arg : slice(arguments, 1); if (err) { rest = 0; runningTasks = 0; readyTasks.length = 0; var safeResults = objectClone(results); safeResults[key] = arg; key = null; var _callback = callback; callback = noop; _callback(err, safeResults); return; } runningTasks--; rest--; results[key] = arg; taskComplete(key); key = null; } function taskListener() { if (--dependencySize === 0) { readyTasks.push([_task, _taskSize, done]); } } } function proceedQueue() { if (readyTasks.length === 0 && runningTasks === 0) { if (rest !== 0) { throw new Error('async.auto task has cyclic dependencies'); } return callback(null, results); } while (readyTasks.length && runningTasks < concurrency && callback !== noop) { runningTasks++; var array = readyTasks.shift(); if (array[1] === 0) { array[0](array[2]); } else { array[0](results, array[2]); } } } function taskComplete(key) { var taskListeners = listeners[key] || []; arrayEachSync(taskListeners, function(task) { task(); }); proceedQueue(); } } var FN_ARGS = /^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m; var FN_ARG_SPLIT = /,/; var FN_ARG = /(=.+)?(\s*)$/; var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; /** * parse function arguments for `autoInject` * * @private */ function parseParams(func) { func = func.toString().replace(STRIP_COMMENTS, ''); func = func.match(FN_ARGS)[2].replace(' ', ''); func = func ? func.split(FN_ARG_SPLIT) : []; func = func.map(function (arg) { return arg.replace(FN_ARG, '').trim(); }); return func; } /** * @memberof async * @namespace autoInject * @param {Object} tasks * @param {number} [concurrency] * @param {Function} [callback] */ function autoInject(tasks, concurrency, callback) { var newTasks = {}; baseEachSync(tasks, iterator, nativeKeys(tasks)); auto(newTasks, concurrency, callback); function iterator(task, key) { var params; var taskLength = task.length; if (isArray(task)) { if (taskLength === 0) { throw new Error('autoInject task functions require explicit parameters.'); } params = createArray(task); taskLength = params.length - 1; task = params[taskLength]; if (taskLength === 0) { newTasks[key] = task; return; } } else if (taskLength === 1) { newTasks[key] = task; return; } else { params = parseParams(task); if (taskLength === 0 && params.length === 0) { throw new Error('autoInject task functions require explicit parameters.'); } taskLength = params.length - 1; } params[taskLength] = newTask; newTasks[key] = params; function newTask(results, done) { switch (taskLength) { case 1: task(results[params[0]], done); break; case 2: task(results[params[0]], results[params[1]], done); break; case 3: task(results[params[0]], results[params[1]], results[params[2]], done); break; default: var i = -1; while(++i < taskLength) { params[i] = results[params[i]]; } params[i] = done; task.apply(null, params); break; } } } } /** * @memberof async * @namespace retry * @param {integer|Object|Function} opts * @param {Function} [task] * @param {Function} [callback] */ function retry(opts, task, callback) { var times, intervalFunc, errorFilter; var count = 0; if (arguments.length < 3 && typeof opts === func) { callback = task || noop; task = opts; opts = null; times = DEFAULT_TIMES; } else { callback = callback || noop; switch (typeof opts) { case 'object': if (typeof opts.errorFilter === func) { errorFilter = opts.errorFilter; } var interval = opts.interval; switch (typeof interval) { case func: intervalFunc = interval; break; case 'string': case 'number': interval = +interval; intervalFunc = interval ? function() { return interval; } : function() { return DEFAULT_INTERVAL; }; break; } times = +opts.times || DEFAULT_TIMES; break; case 'number': times = opts || DEFAULT_TIMES; break; case 'string': times = +opts || DEFAULT_TIMES; break; default: throw new Error('Invalid arguments for async.retry'); } } if (typeof task !== 'function') { throw new Error('Invalid arguments for async.retry'); } if (intervalFunc) { task(intervalCallback); } else { task(simpleCallback); } function simpleIterator() { task(simpleCallback); } function simpleCallback(err, res) { if (++count === times || !err || errorFilter && !errorFilter(err)) { if (arguments.length <= 2) { return callback(err, res); } var args = createArray(arguments); return callback.apply(null, args); } simpleIterator(); } function intervalIterator() { task(intervalCallback); } function intervalCallback(err, res) { if (++count === times || !err || errorFilter && !errorFilter(err)) { if (arguments.length <= 2) { return callback(err, res); } var args = createArray(arguments); return callback.apply(null, args); } setTimeout(intervalIterator, intervalFunc(count)); } } function retryable(opts, task) { if (!task) { task = opts; opts = null; } return done; function done() { var taskFn; var args = createArray(arguments); var lastIndex = args.length - 1; var callback = args[lastIndex]; switch (task.length) { case 1: taskFn = task1; break; case 2: taskFn = task2; break; case 3: taskFn = task3; break; default: taskFn = task4; } if (opts) { retry(opts, taskFn, callback); } else { retry(taskFn, callback); } function task1(done) { task(done); } function task2(done) { task(args[0], done); } function task3(done) { task(args[0], args[1], done); } function task4(callback) { args[lastIndex] = callback; task.apply(null, args); } } } /** * @memberof async * @namespace iterator */ function iterator(tasks) { var size = 0; var keys = []; if (isArray(tasks)) { size = tasks.length; } else { keys = nativeKeys(tasks); size = keys.length; } return makeCallback(0); function makeCallback(index) { var fn = function() { if (size) { var key = keys[index] || index; tasks[key].apply(null, createArray(arguments)); } return fn.next(); }; fn.next = function() { return (index < size - 1) ? makeCallback(index + 1) : null; }; return fn; } } /** * @memberof async * @namespace apply */ function apply(func) { switch (arguments.length) { case 0: case 1: return func; case 2: return func.bind(null, arguments[1]); case 3: return func.bind(null, arguments[1], arguments[2]); case 4: return func.bind(null, arguments[1], arguments[2], arguments[3]); case 5: return func.bind(null, arguments[1], arguments[2], arguments[3], arguments[4]); default: var size = arguments.length; var index = 0; var args = Array(size); args[index] = null; while (++index < size) { args[index] = arguments[index]; } return func.bind.apply(func, args); } } /** * @memberof async * @namespace timeout * @param {Function} func * @param {number} millisec * @param {*} info */ function timeout(func, millisec, info) { var callback, timer; return wrappedFunc; function wrappedFunc() { timer = setTimeout(timeoutCallback, millisec); var args = createArray(arguments); var lastIndex = args.length - 1; callback = args[lastIndex]; args[lastIndex] = injectedCallback; simpleApply(func, args); } function timeoutCallback() { var name = func.name || 'anonymous'; var err = new Error('Callback function "' + name + '" timed out.'); err.code = 'ETIMEDOUT'; if (info) { err.info = info; } timer = null; callback(err); } function injectedCallback() { if (timer !== null) { simpleApply(callback, createArray(arguments)); clearTimeout(timer); } } function simpleApply(func, args) { switch(args.length) { case 0: func(); break; case 1: func(args[0]); break; case 2: func(args[0], args[1]); break; default: func.apply(null, args); break; } } } /** * @memberof async * @namespace times * @param {number} n - n >= 1 * @param {Function} iterator * @param {Function} callback * @example * * var iterator = function(n, done) { * done(null, n); * }; * async.times(4, iterator, function(err, res) { * console.log(res); // [0, 1, 2, 3]; * }); * */ function times(n, iterator, callback) { callback = callback || noop; n = +n; if (isNaN(n) || n < 1) { return callback(null, []); } var result = Array(n); timesSync(n, iterate); function iterate(num) { iterator(num, createCallback(num)); } function createCallback(index) { return function(err, res) { if (index === null) { throwError(); } result[index] = res; index = null; if (err) { callback(err); callback = noop; } else if (--n === 0) { callback(null, result); } }; } } /** * @memberof async * @namespace timesSeries * @param {number} n - n >= 1 * @param {Function} iterator * @param {Function} callback * @example * * var iterator = function(n, done) { * done(null, n); * }; * async.timesSeries(4, iterator, function(err, res) { * console.log(res); // [0, 1, 2, 3]; * }); * */ function timesSeries(n, iterator, callback) { callback = callback || noop; n = +n; if (isNaN(n) || n < 1) { return callback(null, []); } var result = Array(n); var sync = false; var completed = 0; iterate(); function iterate() { iterator(completed, done); } function done(err, res) { result[completed] = res; if (err) { callback(err); callback = throwError; } else if (++completed >= n) { callback(null, result); callback = throwError; } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; } } /** * @memberof async * @namespace timesLimit * @param {number} n - n >= 1 * @param {number} limit - n >= 1 * @param {Function} iterator * @param {Function} callback * @example * * var iterator = function(n, done) { * done(null, n); * }; * async.timesLimit(4, 2, iterator, function(err, res) { * console.log(res); // [0, 1, 2, 3]; * }); * */ function timesLimit(n, limit, iterator, callback) { callback = callback || noop; n = +n; if (isNaN(n) || n < 1 || isNaN(limit) || limit < 1) { return callback(null, []); } var result = Array(n); var sync = false; var started = 0; var completed = 0; timesSync(limit > n ? n : limit, iterate); function iterate() { var index = started++; if (index < n) { iterator(index, createCallback(index)); } } function createCallback(index) { return function(err, res) { if (index === null) { throwError(); } result[index] = res; index = null; if (err) { callback(err); callback = noop; } else if (++completed >= n) { callback(null, result); callback = throwError; } else if (sync) { nextTick(iterate); } else { sync = true; iterate(); } sync = false; }; } } /** * @memberof async * @namespace race * @param {Array|Object} tasks - functions * @param {Function} callback * @example * * // array * var called = 0; * var tasks = [ * function(done) { * setTimeout(function() { * called++; * done(null, '1'); * }, 30); * }, * function(done) { * setTimeout(function() { * called++; * done(null, '2'); * }, 20); * }, * function(done) { * setTimeout(function() { * called++; * done(null, '3'); * }, 10); * } * ]; * async.race(tasks, function(err, res) { * console.log(res); // '3' * console.log(called); // 1 * setTimeout(function() { * console.log(called); // 3 * }, 50); * }); * * @example * * // object * var called = 0; * var tasks = { * 'test1': function(done) { * setTimeout(function() { * called++; * done(null, '1'); * }, 30); * }, * 'test2': function(done) { * setTimeout(function() { * called++; * done(null, '2'); * }, 20); * }, * 'test3': function(done) { * setTimeout(function() { * called++; * done(null, '3'); * }, 10); * } * }; * async.race(tasks, function(err, res) { * console.log(res); // '3' * console.log(called); // 1 * setTimeout(function() { * console.log(called); // 3 * done(); * }, 50); * }); * */ function race(tasks, callback) { callback = once(callback || noop); var size, keys; var index = -1; if (isArray(tasks)) { size = tasks.length; while (++index < size) { tasks[index](callback); } } else if (tasks && typeof tasks === obj) { keys = nativeKeys(tasks); size = keys.length; while (++index < size) { tasks[keys[index]](callback); } } else { return callback(new TypeError('First argument to race must be a collection of functions')); } if (!size) { callback(null); } } /** * @memberof async * @namespace memoize */ function memoize(fn, hasher) { hasher = hasher || function(hash) { return hash; }; var memo = {}; var queues = {}; var memoized = function() { var args = createArray(arguments); var callback = args.pop(); var key = hasher.apply(null, args); if (has(memo, key)) { nextTick(function() { callback.apply(null, memo[key]); }); return; } if (has(queues, key)) { return queues[key].push(callback); } queues[key] = [callback]; args.push(done); fn.apply(null, args); function done() { var args = createArray(arguments); memo[key] = args; var q = queues[key]; delete queues[key]; var i = -1; var size = q.length; while (++i < size) { q[i].apply(null, args); } } }; memoized.memo = memo; memoized.unmemoized = fn; return memoized; } /** * @memberof async * @namespace unmemoize */ function unmemoize(fn) { return function() { return (fn.unmemoized || fn).apply(null, arguments); }; } /** * @memberof async * @namespace ensureAsync */ function ensureAsync(fn) { return function( /* ...args, callback */ ) { var args = createArray(arguments); var lastIndex = args.length - 1; var callback = args[lastIndex]; var sync = true; args[lastIndex] = done; fn.apply(this, args); sync = false; function done() { var innerArgs = createArray(arguments); if (sync) { nextTick(function() { callback.apply(null, innerArgs); }); } else { callback.apply(null, innerArgs); } } }; } /** * @memberof async * @namespace constant */ function constant( /* values... */ ) { var args = [null].concat(createArray(arguments)); return function(callback) { callback = arguments[arguments.length - 1]; callback.apply(this, args); }; } function asyncify(fn) { return function( /* args..., callback */ ) { var args = createArray(arguments); var callback = args.pop(); var result; try { result = fn.apply(this, args); } catch (e) { return callback(e); } if (result && typeof result.then === func) { result.then(function(value) { invokeCallback(callback, null, value); }, function(err) { invokeCallback(callback, err && err.message ? err : new Error(err)); }); } else { callback(null, result); } }; } function invokeCallback(callback, err, value) { try { callback(err, value); } catch (e) { nextTick(rethrow, e); } } function rethrow(error) { throw error; } /** * @memberof async * @namespace reflect * @param {Function} func * @return {Function} */ function reflect(func) { return function( /* args..., callback */ ) { var callback; switch (arguments.length) { case 1: callback = arguments[0]; return func(done); case 2: callback = arguments[1]; return func(arguments[0], done); default: var args = createArray(arguments); var lastIndex = args.length - 1; callback = args[lastIndex]; args[lastIndex] = done; func.apply(this, args); } function done(err, res) { if (err) { return callback(null, { error: err }); } if (arguments.length > 2) { res = slice(arguments, 1); } callback(null, { value: res }); } }; } /** * @memberof async * @namespace reflectAll * @param {Array[]|Object} tasks * @return {Function} */ function reflectAll(tasks) { var size, newTasks, keys; if (isArray(tasks)) { size = tasks.length; newTasks = Array(size); arrayEachSync(tasks, iterate); } else if (tasks && typeof tasks === obj) { keys = nativeKeys(tasks); size = keys.length; newTasks = {}; baseEachSync(tasks, iterate, keys); } return newTasks; function iterate(func, key) { newTasks[key] = reflect(func); } } /** * @memberof async * @namespace createLogger */ function createLogger(name) { return function(fn) { var args = slice(arguments, 1); args.push(done); fn.apply(null, args); }; function done(err) { if (typeof console === obj) { if (err) { if (console.error) { console.error(err); } return; } if (console[name]) { var args = slice(arguments, 1); arrayEachSync(args, function(arg) { console[name](arg); }); } } } } /** * @memberof async * @namespace safe */ function safe() { createImmediate(); return exports; } /** * @memberof async * @namespace fast */ function fast() { createImmediate(false); return exports; } }));