summaryrefslogtreecommitdiffstats
path: root/node_modules/neo-async/async.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/neo-async/async.js')
-rw-r--r--node_modules/neo-async/async.js9184
1 files changed, 9184 insertions, 0 deletions
diff --git a/node_modules/neo-async/async.js b/node_modules/neo-async/async.js
new file mode 100644
index 0000000..e78eb16
--- /dev/null
+++ b/node_modules/neo-async/async.js
@@ -0,0 +1,9184 @@
+(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.6.2
+ * @namespace async
+ */
+ var index = {
+ VERSION: '2.6.2',
+
+ // 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 = 0;
+ 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) {
+ index++;
+ iterator(item.value, onlyOnce(callback));
+ }
+ }
+ return index;
+ }
+
+ /**
+ * @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 = 0;
+ 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) {
+ index++;
+ iterator(result, item.value, onlyOnce(callback));
+ }
+ }
+ return index;
+ }
+
+ /**
+ * @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 item;
+ var index = 0;
+ 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++));
+ }
+ }
+ return 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 = 0;
+ 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++));
+ }
+ }
+ return 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 = 0;
+ 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) {
+ index++;
+ value = item.value;
+ iterator(value, createCallback(value));
+ }
+ }
+ return index;
+ }
+
+ /**
+ * @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 = 0;
+ 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));
+ }
+ }
+ return index;
+ }
+
+ /**
+ * @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 = 0;
+ 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));
+ }
+ }
+ return index;
+ }
+
+ /**
+ * @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 = once(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 = symbolEach(collection, iterator, done);
+ size && size === completed && callback(null);
+ } 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]) {
+ // TODO: size could be changed
+ result = init(0);
+ size = symbolEach(collection, iterator, createCallback);
+ size && size === completed && callback(null, result);
+ } 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]) {
+ result = [];
+ size = symbolEach(collection, iterator, createCallback);
+ size && size === completed && callback(null, compact(result));
+ } 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, item, 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 = Infinity;
+ 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() {
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null, result) : iterator(value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null, result) : 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 = Infinity;
+ result = [];
+ 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 = 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() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ iterator(value, createCallback(value, started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, compact(result));
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ iterator(value, started, createCallback(value, started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, compact(result));
+ }
+ }
+
+ 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, item, 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 = Infinity;
+ 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() {
+ item = iter.next();
+ item.done ? callback(null) : iterator(item.value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ item.done ? callback(null) : iterator(item.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 || 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 = Infinity;
+ 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() {
+ item = iter.next();
+ if (item.done === false) {
+ started++;
+ iterator(item.value, done);
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null);
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(item.value, started++, done);
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null);
+ }
+ }
+
+ 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 || bool === false) {
+ iterate = noop;
+ callback = once(callback);
+ callback(err);
+ } else if (++completed === size) {
+ iterator = noop;
+ iterate = throwError;
+ callback = onlyOnce(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, item, 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 = Infinity;
+ result = [];
+ 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 = result || Array(size);
+ iterate();
+
+ function arrayIterator() {
+ iterator(collection[completed], done);
+ }
+
+ function arrayIteratorWithIndex() {
+ iterator(collection[completed], completed, done);
+ }
+
+ function symbolIterator() {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(item.value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(item.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 = Infinity;
+ result = [];
+ 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 = 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() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(item.value, createCallback(started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(item.value, started, createCallback(started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ 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, item, 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 = Infinity;
+ 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;
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(item.value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ key = completed;
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(item.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 = Infinity;
+ 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() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(item.value, createCallback(started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(item.value, started, createCallback(started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ 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 = symbolEach(collection, iterator, createCallback);
+ size && size === completed && callback(null);
+ } 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, item, 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 = Infinity;
+ 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() {
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null) : iterator(value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null) : 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 = Infinity;
+ 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() {
+ item = iter.next();
+ if (item.done === false) {
+ started++;
+ value = item.value;
+ iterator(value, createCallback(value));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null);
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ iterator(value, started++, createCallback(value));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null);
+ }
+ }
+
+ 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 = symbolEach(collection, iterator, createCallback);
+ size && size === completed && callback(null, result);
+ } 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, item, 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 = Infinity;
+ 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;
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null, result) : iterator(value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ key = completed;
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null, result) : 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 = Infinity;
+ 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() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ iterator(value, createCallback(value, started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ iterator(value, started, createCallback(value, started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ 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, item, iterate;
+ var sync = false;
+ var completed = 0;
+
+ if (isArray(collection)) {
+ size = collection.length;
+ iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator;
+ } else if (!collection) {
+ } else if (iteratorSymbol && collection[iteratorSymbol]) {
+ size = Infinity;
+ iter = collection[iteratorSymbol]();
+ iterate = iterator.length === 4 ? symbolIteratorWithKey : symbolIterator;
+ } else if (typeof collection === obj) {
+ keys = nativeKeys(collection);
+ size = keys.length;
+ iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator;
+ }
+ if (!size) {
+ return callback(null, result);
+ }
+ iterate(result);
+
+ function arrayIterator(result) {
+ iterator(result, collection[completed], done);
+ }
+
+ function arrayIteratorWithIndex(result) {
+ iterator(result, collection[completed], completed, done);
+ }
+
+ function symbolIterator(result) {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(result, item.value, done);
+ }
+
+ function symbolIteratorWithKey(result) {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(result, item.value, completed, done);
+ }
+
+ function objectIterator(result) {
+ iterator(result, collection[keys[completed]], done);
+ }
+
+ function objectIteratorWithKey(result) {
+ key = keys[completed];
+ iterator(result, collection[key], key, done);
+ }
+
+ function done(err, result) {
+ 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]) {
+ col = [];
+ iter = collection[iteratorSymbol]();
+ index = -1;
+ while ((item = iter.next()).done === false) {
+ col[++index] = item.value;
+ }
+ collection = col;
+ resIndex = col.length;
+ iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator;
+ } else if (typeof collection === obj) {
+ keys = nativeKeys(collection);
+ resIndex = keys.length;
+ iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator;
+ }
+ if (!resIndex) {
+ return callback(null, result);
+ }
+ iterate(result);
+
+ function arrayIterator(result) {
+ iterator(result, collection[--resIndex], done);
+ }
+
+ function arrayIteratorWithIndex(result) {
+ iterator(result, collection[--resIndex], resIndex, done);
+ }
+
+ function objectIterator(result) {
+ iterator(result, collection[keys[--resIndex]], done);
+ }
+
+ function objectIteratorWithKey(result) {
+ key = keys[--resIndex];
+ iterator(result, collection[key], key, done);
+ }
+
+ function done(err, result) {
+ if (err) {
+ callback(err, result);
+ } else if (resIndex === 0) {
+ iterate = throwError;
+ callback(null, result);
+ } else if (sync) {
+ nextTick(function() {
+ iterate(result);
+ });
+ } else {
+ sync = true;
+ iterate(result);
+ }
+ sync = false;
+ }
+ }
+
+ /**
+ * @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]) {
+ result = accumulator !== undefined ? accumulator : {};
+ size = symbolEach(collection, result, iterator, done);
+ size && size === completed && callback(null, result);
+ } 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, item, 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 = Infinity;
+ 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() {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(result, item.value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(result, item.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 || 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 = Infinity;
+ 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() {
+ item = iter.next();
+ if (item.done === false) {
+ started++;
+ iterator(result, item.value, onlyOnce(done));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(result, item.value, started++, onlyOnce(done));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ 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 || bool === false) {
+ iterate = noop;
+ callback(err || null, isArray(result) ? createArray(result) : objectClone(result));
+ callback = noop;
+ } else if (++completed === size) {
+ iterator = noop;
+ callback(null, result);
+ } 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]) {
+ array = [];
+ criteria = [];
+ size = symbolEach(collection, iterator, createCallback);
+ size && size === completed && callback(null, sortByCriteria(array, criteria));
+ } 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, item, 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 = Infinity;
+ array = [];
+ criteria = [];
+ 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() {
+ item = iter.next();
+ if (item.done) {
+ return callback(null, sortByCriteria(array, criteria));
+ }
+ value = item.value;
+ array[completed] = value;
+ iterator(value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done) {
+ return callback(null, sortByCriteria(array, criteria));
+ }
+ value = item.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 = Infinity;
+ iter = collection[iteratorSymbol]();
+ array = [];
+ criteria = [];
+ 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 = 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() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ array[started] = value;
+ iterator(value, createCallback(value, started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, sortByCriteria(array, criteria));
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ array[started] = value;
+ iterator(value, started, createCallback(value, started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, sortByCriteria(array, criteria));
+ }
+ }
+
+ 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]) {
+ result = [];
+ size = symbolEach(collection, iterator, createCallback);
+ size && size === completed && callback(null, result);
+ } 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, item, 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 = Infinity;
+ 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() {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(item.value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ item.done ? callback(null, result) : iterator(item.value, 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, 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 = Infinity;
+ result = [];
+ 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, []);
+ }
+ result = 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() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(item.value, createCallback(started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, makeConcatResult(result));
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ iterator(item.value, started, createCallback(started++));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, makeConcatResult(result));
+ }
+ }
+
+ 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 = symbolEach(collection, iterator, createCallback);
+ size && size === completed && callback(null, result);
+ } 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) {
+ 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, item, 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 = Infinity;
+ 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() {
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null, result) : iterator(value, done);
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ value = item.value;
+ item.done ? callback(null, result) : 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) {
+ 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 = Infinity;
+ 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() {
+ item = iter.next();
+ if (item.done === false) {
+ started++;
+ value = item.value;
+ iterator(value, createCallback(value));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ function symbolIteratorWithKey() {
+ item = iter.next();
+ if (item.done === false) {
+ value = item.value;
+ iterator(value, started++, createCallback(value));
+ } else if (completed === started && iterator !== noop) {
+ iterator = noop;
+ callback(null, result);
+ }
+ }
+
+ 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);
+ // Avoid leaking the callback
+ _callback = undefined;
+ }
+
+ 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) {
+ if (index === 0) {
+ workersList.shift();
+ } else {
+ 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 = new DLL();
+ 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]*?\*\/))/gm;
+
+ /**
+ * 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(err) {
+ var args = createArray(arguments);
+ if (!err) {
+ 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 newTasks, keys;
+ if (isArray(tasks)) {
+ newTasks = Array(tasks.length);
+ arrayEachSync(tasks, iterate);
+ } else if (tasks && typeof tasks === obj) {
+ keys = nativeKeys(tasks);
+ 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;
+ }
+});