Projekt

Obecné

Profil

Stáhnout (181 KB) Statistiky
| Větev: | Revize:
1
(function (global, factory) {
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
  (factory((global.async = global.async || {})));
5
}(this, (function (exports) { 'use strict';
6

    
7
function slice(arrayLike, start) {
8
    start = start|0;
9
    var newLen = Math.max(arrayLike.length - start, 0);
10
    var newArr = Array(newLen);
11
    for(var idx = 0; idx < newLen; idx++)  {
12
        newArr[idx] = arrayLike[start + idx];
13
    }
14
    return newArr;
15
}
16

    
17
/**
18
 * Creates a continuation function with some arguments already applied.
19
 *
20
 * Useful as a shorthand when combined with other control flow functions. Any
21
 * arguments passed to the returned function are added to the arguments
22
 * originally passed to apply.
23
 *
24
 * @name apply
25
 * @static
26
 * @memberOf module:Utils
27
 * @method
28
 * @category Util
29
 * @param {Function} fn - The function you want to eventually apply all
30
 * arguments to. Invokes with (arguments...).
31
 * @param {...*} arguments... - Any number of arguments to automatically apply
32
 * when the continuation is called.
33
 * @returns {Function} the partially-applied function
34
 * @example
35
 *
36
 * // using apply
37
 * async.parallel([
38
 *     async.apply(fs.writeFile, 'testfile1', 'test1'),
39
 *     async.apply(fs.writeFile, 'testfile2', 'test2')
40
 * ]);
41
 *
42
 *
43
 * // the same process without using apply
44
 * async.parallel([
45
 *     function(callback) {
46
 *         fs.writeFile('testfile1', 'test1', callback);
47
 *     },
48
 *     function(callback) {
49
 *         fs.writeFile('testfile2', 'test2', callback);
50
 *     }
51
 * ]);
52
 *
53
 * // It's possible to pass any number of additional arguments when calling the
54
 * // continuation:
55
 *
56
 * node> var fn = async.apply(sys.puts, 'one');
57
 * node> fn('two', 'three');
58
 * one
59
 * two
60
 * three
61
 */
62
var apply = function(fn/*, ...args*/) {
63
    var args = slice(arguments, 1);
64
    return function(/*callArgs*/) {
65
        var callArgs = slice(arguments);
66
        return fn.apply(null, args.concat(callArgs));
67
    };
68
};
69

    
70
var initialParams = function (fn) {
71
    return function (/*...args, callback*/) {
72
        var args = slice(arguments);
73
        var callback = args.pop();
74
        fn.call(this, args, callback);
75
    };
76
};
77

    
78
/**
79
 * Checks if `value` is the
80
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
81
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
82
 *
83
 * @static
84
 * @memberOf _
85
 * @since 0.1.0
86
 * @category Lang
87
 * @param {*} value The value to check.
88
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
89
 * @example
90
 *
91
 * _.isObject({});
92
 * // => true
93
 *
94
 * _.isObject([1, 2, 3]);
95
 * // => true
96
 *
97
 * _.isObject(_.noop);
98
 * // => true
99
 *
100
 * _.isObject(null);
101
 * // => false
102
 */
103
function isObject(value) {
104
  var type = typeof value;
105
  return value != null && (type == 'object' || type == 'function');
106
}
107

    
108
var hasSetImmediate = typeof setImmediate === 'function' && setImmediate;
109
var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function';
110

    
111
function fallback(fn) {
112
    setTimeout(fn, 0);
113
}
114

    
115
function wrap(defer) {
116
    return function (fn/*, ...args*/) {
117
        var args = slice(arguments, 1);
118
        defer(function () {
119
            fn.apply(null, args);
120
        });
121
    };
122
}
123

    
124
var _defer;
125

    
126
if (hasSetImmediate) {
127
    _defer = setImmediate;
128
} else if (hasNextTick) {
129
    _defer = process.nextTick;
130
} else {
131
    _defer = fallback;
132
}
133

    
134
var setImmediate$1 = wrap(_defer);
135

    
136
/**
137
 * Take a sync function and make it async, passing its return value to a
138
 * callback. This is useful for plugging sync functions into a waterfall,
139
 * series, or other async functions. Any arguments passed to the generated
140
 * function will be passed to the wrapped function (except for the final
141
 * callback argument). Errors thrown will be passed to the callback.
142
 *
143
 * If the function passed to `asyncify` returns a Promise, that promises's
144
 * resolved/rejected state will be used to call the callback, rather than simply
145
 * the synchronous return value.
146
 *
147
 * This also means you can asyncify ES2017 `async` functions.
148
 *
149
 * @name asyncify
150
 * @static
151
 * @memberOf module:Utils
152
 * @method
153
 * @alias wrapSync
154
 * @category Util
155
 * @param {Function} func - The synchronous function, or Promise-returning
156
 * function to convert to an {@link AsyncFunction}.
157
 * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
158
 * invoked with `(args..., callback)`.
159
 * @example
160
 *
161
 * // passing a regular synchronous function
162
 * async.waterfall([
163
 *     async.apply(fs.readFile, filename, "utf8"),
164
 *     async.asyncify(JSON.parse),
165
 *     function (data, next) {
166
 *         // data is the result of parsing the text.
167
 *         // If there was a parsing error, it would have been caught.
168
 *     }
169
 * ], callback);
170
 *
171
 * // passing a function returning a promise
172
 * async.waterfall([
173
 *     async.apply(fs.readFile, filename, "utf8"),
174
 *     async.asyncify(function (contents) {
175
 *         return db.model.create(contents);
176
 *     }),
177
 *     function (model, next) {
178
 *         // `model` is the instantiated model object.
179
 *         // If there was an error, this function would be skipped.
180
 *     }
181
 * ], callback);
182
 *
183
 * // es2017 example, though `asyncify` is not needed if your JS environment
184
 * // supports async functions out of the box
185
 * var q = async.queue(async.asyncify(async function(file) {
186
 *     var intermediateStep = await processFile(file);
187
 *     return await somePromise(intermediateStep)
188
 * }));
189
 *
190
 * q.push(files);
191
 */
192
function asyncify(func) {
193
    return initialParams(function (args, callback) {
194
        var result;
195
        try {
196
            result = func.apply(this, args);
197
        } catch (e) {
198
            return callback(e);
199
        }
200
        // if result is Promise object
201
        if (isObject(result) && typeof result.then === 'function') {
202
            result.then(function(value) {
203
                invokeCallback(callback, null, value);
204
            }, function(err) {
205
                invokeCallback(callback, err.message ? err : new Error(err));
206
            });
207
        } else {
208
            callback(null, result);
209
        }
210
    });
211
}
212

    
213
function invokeCallback(callback, error, value) {
214
    try {
215
        callback(error, value);
216
    } catch (e) {
217
        setImmediate$1(rethrow, e);
218
    }
219
}
220

    
221
function rethrow(error) {
222
    throw error;
223
}
224

    
225
var supportsSymbol = typeof Symbol === 'function';
226

    
227
function isAsync(fn) {
228
    return supportsSymbol && fn[Symbol.toStringTag] === 'AsyncFunction';
229
}
230

    
231
function wrapAsync(asyncFn) {
232
    return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn;
233
}
234

    
235
function applyEach$1(eachfn) {
236
    return function(fns/*, ...args*/) {
237
        var args = slice(arguments, 1);
238
        var go = initialParams(function(args, callback) {
239
            var that = this;
240
            return eachfn(fns, function (fn, cb) {
241
                wrapAsync(fn).apply(that, args.concat(cb));
242
            }, callback);
243
        });
244
        if (args.length) {
245
            return go.apply(this, args);
246
        }
247
        else {
248
            return go;
249
        }
250
    };
251
}
252

    
253
/** Detect free variable `global` from Node.js. */
254
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
255

    
256
/** Detect free variable `self`. */
257
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
258

    
259
/** Used as a reference to the global object. */
260
var root = freeGlobal || freeSelf || Function('return this')();
261

    
262
/** Built-in value references. */
263
var Symbol$1 = root.Symbol;
264

    
265
/** Used for built-in method references. */
266
var objectProto = Object.prototype;
267

    
268
/** Used to check objects for own properties. */
269
var hasOwnProperty = objectProto.hasOwnProperty;
270

    
271
/**
272
 * Used to resolve the
273
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
274
 * of values.
275
 */
276
var nativeObjectToString = objectProto.toString;
277

    
278
/** Built-in value references. */
279
var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined;
280

    
281
/**
282
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
283
 *
284
 * @private
285
 * @param {*} value The value to query.
286
 * @returns {string} Returns the raw `toStringTag`.
287
 */
288
function getRawTag(value) {
289
  var isOwn = hasOwnProperty.call(value, symToStringTag$1),
290
      tag = value[symToStringTag$1];
291

    
292
  try {
293
    value[symToStringTag$1] = undefined;
294
    var unmasked = true;
295
  } catch (e) {}
296

    
297
  var result = nativeObjectToString.call(value);
298
  if (unmasked) {
299
    if (isOwn) {
300
      value[symToStringTag$1] = tag;
301
    } else {
302
      delete value[symToStringTag$1];
303
    }
304
  }
305
  return result;
306
}
307

    
308
/** Used for built-in method references. */
309
var objectProto$1 = Object.prototype;
310

    
311
/**
312
 * Used to resolve the
313
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
314
 * of values.
315
 */
316
var nativeObjectToString$1 = objectProto$1.toString;
317

    
318
/**
319
 * Converts `value` to a string using `Object.prototype.toString`.
320
 *
321
 * @private
322
 * @param {*} value The value to convert.
323
 * @returns {string} Returns the converted string.
324
 */
325
function objectToString(value) {
326
  return nativeObjectToString$1.call(value);
327
}
328

    
329
/** `Object#toString` result references. */
330
var nullTag = '[object Null]';
331
var undefinedTag = '[object Undefined]';
332

    
333
/** Built-in value references. */
334
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined;
335

    
336
/**
337
 * The base implementation of `getTag` without fallbacks for buggy environments.
338
 *
339
 * @private
340
 * @param {*} value The value to query.
341
 * @returns {string} Returns the `toStringTag`.
342
 */
343
function baseGetTag(value) {
344
  if (value == null) {
345
    return value === undefined ? undefinedTag : nullTag;
346
  }
347
  return (symToStringTag && symToStringTag in Object(value))
348
    ? getRawTag(value)
349
    : objectToString(value);
350
}
351

    
352
/** `Object#toString` result references. */
353
var asyncTag = '[object AsyncFunction]';
354
var funcTag = '[object Function]';
355
var genTag = '[object GeneratorFunction]';
356
var proxyTag = '[object Proxy]';
357

    
358
/**
359
 * Checks if `value` is classified as a `Function` object.
360
 *
361
 * @static
362
 * @memberOf _
363
 * @since 0.1.0
364
 * @category Lang
365
 * @param {*} value The value to check.
366
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
367
 * @example
368
 *
369
 * _.isFunction(_);
370
 * // => true
371
 *
372
 * _.isFunction(/abc/);
373
 * // => false
374
 */
375
function isFunction(value) {
376
  if (!isObject(value)) {
377
    return false;
378
  }
379
  // The use of `Object#toString` avoids issues with the `typeof` operator
380
  // in Safari 9 which returns 'object' for typed arrays and other constructors.
381
  var tag = baseGetTag(value);
382
  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
383
}
384

    
385
/** Used as references for various `Number` constants. */
386
var MAX_SAFE_INTEGER = 9007199254740991;
387

    
388
/**
389
 * Checks if `value` is a valid array-like length.
390
 *
391
 * **Note:** This method is loosely based on
392
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
393
 *
394
 * @static
395
 * @memberOf _
396
 * @since 4.0.0
397
 * @category Lang
398
 * @param {*} value The value to check.
399
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
400
 * @example
401
 *
402
 * _.isLength(3);
403
 * // => true
404
 *
405
 * _.isLength(Number.MIN_VALUE);
406
 * // => false
407
 *
408
 * _.isLength(Infinity);
409
 * // => false
410
 *
411
 * _.isLength('3');
412
 * // => false
413
 */
414
function isLength(value) {
415
  return typeof value == 'number' &&
416
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
417
}
418

    
419
/**
420
 * Checks if `value` is array-like. A value is considered array-like if it's
421
 * not a function and has a `value.length` that's an integer greater than or
422
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
423
 *
424
 * @static
425
 * @memberOf _
426
 * @since 4.0.0
427
 * @category Lang
428
 * @param {*} value The value to check.
429
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
430
 * @example
431
 *
432
 * _.isArrayLike([1, 2, 3]);
433
 * // => true
434
 *
435
 * _.isArrayLike(document.body.children);
436
 * // => true
437
 *
438
 * _.isArrayLike('abc');
439
 * // => true
440
 *
441
 * _.isArrayLike(_.noop);
442
 * // => false
443
 */
444
function isArrayLike(value) {
445
  return value != null && isLength(value.length) && !isFunction(value);
446
}
447

    
448
// A temporary value used to identify if the loop should be broken.
449
// See #1064, #1293
450
var breakLoop = {};
451

    
452
/**
453
 * This method returns `undefined`.
454
 *
455
 * @static
456
 * @memberOf _
457
 * @since 2.3.0
458
 * @category Util
459
 * @example
460
 *
461
 * _.times(2, _.noop);
462
 * // => [undefined, undefined]
463
 */
464
function noop() {
465
  // No operation performed.
466
}
467

    
468
function once(fn) {
469
    return function () {
470
        if (fn === null) return;
471
        var callFn = fn;
472
        fn = null;
473
        callFn.apply(this, arguments);
474
    };
475
}
476

    
477
var iteratorSymbol = typeof Symbol === 'function' && Symbol.iterator;
478

    
479
var getIterator = function (coll) {
480
    return iteratorSymbol && coll[iteratorSymbol] && coll[iteratorSymbol]();
481
};
482

    
483
/**
484
 * The base implementation of `_.times` without support for iteratee shorthands
485
 * or max array length checks.
486
 *
487
 * @private
488
 * @param {number} n The number of times to invoke `iteratee`.
489
 * @param {Function} iteratee The function invoked per iteration.
490
 * @returns {Array} Returns the array of results.
491
 */
492
function baseTimes(n, iteratee) {
493
  var index = -1,
494
      result = Array(n);
495

    
496
  while (++index < n) {
497
    result[index] = iteratee(index);
498
  }
499
  return result;
500
}
501

    
502
/**
503
 * Checks if `value` is object-like. A value is object-like if it's not `null`
504
 * and has a `typeof` result of "object".
505
 *
506
 * @static
507
 * @memberOf _
508
 * @since 4.0.0
509
 * @category Lang
510
 * @param {*} value The value to check.
511
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
512
 * @example
513
 *
514
 * _.isObjectLike({});
515
 * // => true
516
 *
517
 * _.isObjectLike([1, 2, 3]);
518
 * // => true
519
 *
520
 * _.isObjectLike(_.noop);
521
 * // => false
522
 *
523
 * _.isObjectLike(null);
524
 * // => false
525
 */
526
function isObjectLike(value) {
527
  return value != null && typeof value == 'object';
528
}
529

    
530
/** `Object#toString` result references. */
531
var argsTag = '[object Arguments]';
532

    
533
/**
534
 * The base implementation of `_.isArguments`.
535
 *
536
 * @private
537
 * @param {*} value The value to check.
538
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
539
 */
540
function baseIsArguments(value) {
541
  return isObjectLike(value) && baseGetTag(value) == argsTag;
542
}
543

    
544
/** Used for built-in method references. */
545
var objectProto$3 = Object.prototype;
546

    
547
/** Used to check objects for own properties. */
548
var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
549

    
550
/** Built-in value references. */
551
var propertyIsEnumerable = objectProto$3.propertyIsEnumerable;
552

    
553
/**
554
 * Checks if `value` is likely an `arguments` object.
555
 *
556
 * @static
557
 * @memberOf _
558
 * @since 0.1.0
559
 * @category Lang
560
 * @param {*} value The value to check.
561
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
562
 *  else `false`.
563
 * @example
564
 *
565
 * _.isArguments(function() { return arguments; }());
566
 * // => true
567
 *
568
 * _.isArguments([1, 2, 3]);
569
 * // => false
570
 */
571
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
572
  return isObjectLike(value) && hasOwnProperty$2.call(value, 'callee') &&
573
    !propertyIsEnumerable.call(value, 'callee');
574
};
575

    
576
/**
577
 * Checks if `value` is classified as an `Array` object.
578
 *
579
 * @static
580
 * @memberOf _
581
 * @since 0.1.0
582
 * @category Lang
583
 * @param {*} value The value to check.
584
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
585
 * @example
586
 *
587
 * _.isArray([1, 2, 3]);
588
 * // => true
589
 *
590
 * _.isArray(document.body.children);
591
 * // => false
592
 *
593
 * _.isArray('abc');
594
 * // => false
595
 *
596
 * _.isArray(_.noop);
597
 * // => false
598
 */
599
var isArray = Array.isArray;
600

    
601
/**
602
 * This method returns `false`.
603
 *
604
 * @static
605
 * @memberOf _
606
 * @since 4.13.0
607
 * @category Util
608
 * @returns {boolean} Returns `false`.
609
 * @example
610
 *
611
 * _.times(2, _.stubFalse);
612
 * // => [false, false]
613
 */
614
function stubFalse() {
615
  return false;
616
}
617

    
618
/** Detect free variable `exports`. */
619
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
620

    
621
/** Detect free variable `module`. */
622
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
623

    
624
/** Detect the popular CommonJS extension `module.exports`. */
625
var moduleExports = freeModule && freeModule.exports === freeExports;
626

    
627
/** Built-in value references. */
628
var Buffer = moduleExports ? root.Buffer : undefined;
629

    
630
/* Built-in method references for those with the same name as other `lodash` methods. */
631
var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;
632

    
633
/**
634
 * Checks if `value` is a buffer.
635
 *
636
 * @static
637
 * @memberOf _
638
 * @since 4.3.0
639
 * @category Lang
640
 * @param {*} value The value to check.
641
 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
642
 * @example
643
 *
644
 * _.isBuffer(new Buffer(2));
645
 * // => true
646
 *
647
 * _.isBuffer(new Uint8Array(2));
648
 * // => false
649
 */
650
var isBuffer = nativeIsBuffer || stubFalse;
651

    
652
/** Used as references for various `Number` constants. */
653
var MAX_SAFE_INTEGER$1 = 9007199254740991;
654

    
655
/** Used to detect unsigned integer values. */
656
var reIsUint = /^(?:0|[1-9]\d*)$/;
657

    
658
/**
659
 * Checks if `value` is a valid array-like index.
660
 *
661
 * @private
662
 * @param {*} value The value to check.
663
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
664
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
665
 */
666
function isIndex(value, length) {
667
  var type = typeof value;
668
  length = length == null ? MAX_SAFE_INTEGER$1 : length;
669

    
670
  return !!length &&
671
    (type == 'number' ||
672
      (type != 'symbol' && reIsUint.test(value))) &&
673
        (value > -1 && value % 1 == 0 && value < length);
674
}
675

    
676
/** `Object#toString` result references. */
677
var argsTag$1 = '[object Arguments]';
678
var arrayTag = '[object Array]';
679
var boolTag = '[object Boolean]';
680
var dateTag = '[object Date]';
681
var errorTag = '[object Error]';
682
var funcTag$1 = '[object Function]';
683
var mapTag = '[object Map]';
684
var numberTag = '[object Number]';
685
var objectTag = '[object Object]';
686
var regexpTag = '[object RegExp]';
687
var setTag = '[object Set]';
688
var stringTag = '[object String]';
689
var weakMapTag = '[object WeakMap]';
690

    
691
var arrayBufferTag = '[object ArrayBuffer]';
692
var dataViewTag = '[object DataView]';
693
var float32Tag = '[object Float32Array]';
694
var float64Tag = '[object Float64Array]';
695
var int8Tag = '[object Int8Array]';
696
var int16Tag = '[object Int16Array]';
697
var int32Tag = '[object Int32Array]';
698
var uint8Tag = '[object Uint8Array]';
699
var uint8ClampedTag = '[object Uint8ClampedArray]';
700
var uint16Tag = '[object Uint16Array]';
701
var uint32Tag = '[object Uint32Array]';
702

    
703
/** Used to identify `toStringTag` values of typed arrays. */
704
var typedArrayTags = {};
705
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
706
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
707
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
708
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
709
typedArrayTags[uint32Tag] = true;
710
typedArrayTags[argsTag$1] = typedArrayTags[arrayTag] =
711
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
712
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
713
typedArrayTags[errorTag] = typedArrayTags[funcTag$1] =
714
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
715
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
716
typedArrayTags[setTag] = typedArrayTags[stringTag] =
717
typedArrayTags[weakMapTag] = false;
718

    
719
/**
720
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
721
 *
722
 * @private
723
 * @param {*} value The value to check.
724
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
725
 */
726
function baseIsTypedArray(value) {
727
  return isObjectLike(value) &&
728
    isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
729
}
730

    
731
/**
732
 * The base implementation of `_.unary` without support for storing metadata.
733
 *
734
 * @private
735
 * @param {Function} func The function to cap arguments for.
736
 * @returns {Function} Returns the new capped function.
737
 */
738
function baseUnary(func) {
739
  return function(value) {
740
    return func(value);
741
  };
742
}
743

    
744
/** Detect free variable `exports`. */
745
var freeExports$1 = typeof exports == 'object' && exports && !exports.nodeType && exports;
746

    
747
/** Detect free variable `module`. */
748
var freeModule$1 = freeExports$1 && typeof module == 'object' && module && !module.nodeType && module;
749

    
750
/** Detect the popular CommonJS extension `module.exports`. */
751
var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1;
752

    
753
/** Detect free variable `process` from Node.js. */
754
var freeProcess = moduleExports$1 && freeGlobal.process;
755

    
756
/** Used to access faster Node.js helpers. */
757
var nodeUtil = (function() {
758
  try {
759
    // Use `util.types` for Node.js 10+.
760
    var types = freeModule$1 && freeModule$1.require && freeModule$1.require('util').types;
761

    
762
    if (types) {
763
      return types;
764
    }
765

    
766
    // Legacy `process.binding('util')` for Node.js < 10.
767
    return freeProcess && freeProcess.binding && freeProcess.binding('util');
768
  } catch (e) {}
769
}());
770

    
771
/* Node.js helper references. */
772
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
773

    
774
/**
775
 * Checks if `value` is classified as a typed array.
776
 *
777
 * @static
778
 * @memberOf _
779
 * @since 3.0.0
780
 * @category Lang
781
 * @param {*} value The value to check.
782
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
783
 * @example
784
 *
785
 * _.isTypedArray(new Uint8Array);
786
 * // => true
787
 *
788
 * _.isTypedArray([]);
789
 * // => false
790
 */
791
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
792

    
793
/** Used for built-in method references. */
794
var objectProto$2 = Object.prototype;
795

    
796
/** Used to check objects for own properties. */
797
var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
798

    
799
/**
800
 * Creates an array of the enumerable property names of the array-like `value`.
801
 *
802
 * @private
803
 * @param {*} value The value to query.
804
 * @param {boolean} inherited Specify returning inherited property names.
805
 * @returns {Array} Returns the array of property names.
806
 */
807
function arrayLikeKeys(value, inherited) {
808
  var isArr = isArray(value),
809
      isArg = !isArr && isArguments(value),
810
      isBuff = !isArr && !isArg && isBuffer(value),
811
      isType = !isArr && !isArg && !isBuff && isTypedArray(value),
812
      skipIndexes = isArr || isArg || isBuff || isType,
813
      result = skipIndexes ? baseTimes(value.length, String) : [],
814
      length = result.length;
815

    
816
  for (var key in value) {
817
    if ((inherited || hasOwnProperty$1.call(value, key)) &&
818
        !(skipIndexes && (
819
           // Safari 9 has enumerable `arguments.length` in strict mode.
820
           key == 'length' ||
821
           // Node.js 0.10 has enumerable non-index properties on buffers.
822
           (isBuff && (key == 'offset' || key == 'parent')) ||
823
           // PhantomJS 2 has enumerable non-index properties on typed arrays.
824
           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
825
           // Skip index properties.
826
           isIndex(key, length)
827
        ))) {
828
      result.push(key);
829
    }
830
  }
831
  return result;
832
}
833

    
834
/** Used for built-in method references. */
835
var objectProto$5 = Object.prototype;
836

    
837
/**
838
 * Checks if `value` is likely a prototype object.
839
 *
840
 * @private
841
 * @param {*} value The value to check.
842
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
843
 */
844
function isPrototype(value) {
845
  var Ctor = value && value.constructor,
846
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$5;
847

    
848
  return value === proto;
849
}
850

    
851
/**
852
 * Creates a unary function that invokes `func` with its argument transformed.
853
 *
854
 * @private
855
 * @param {Function} func The function to wrap.
856
 * @param {Function} transform The argument transform.
857
 * @returns {Function} Returns the new function.
858
 */
859
function overArg(func, transform) {
860
  return function(arg) {
861
    return func(transform(arg));
862
  };
863
}
864

    
865
/* Built-in method references for those with the same name as other `lodash` methods. */
866
var nativeKeys = overArg(Object.keys, Object);
867

    
868
/** Used for built-in method references. */
869
var objectProto$4 = Object.prototype;
870

    
871
/** Used to check objects for own properties. */
872
var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
873

    
874
/**
875
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
876
 *
877
 * @private
878
 * @param {Object} object The object to query.
879
 * @returns {Array} Returns the array of property names.
880
 */
881
function baseKeys(object) {
882
  if (!isPrototype(object)) {
883
    return nativeKeys(object);
884
  }
885
  var result = [];
886
  for (var key in Object(object)) {
887
    if (hasOwnProperty$3.call(object, key) && key != 'constructor') {
888
      result.push(key);
889
    }
890
  }
891
  return result;
892
}
893

    
894
/**
895
 * Creates an array of the own enumerable property names of `object`.
896
 *
897
 * **Note:** Non-object values are coerced to objects. See the
898
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
899
 * for more details.
900
 *
901
 * @static
902
 * @since 0.1.0
903
 * @memberOf _
904
 * @category Object
905
 * @param {Object} object The object to query.
906
 * @returns {Array} Returns the array of property names.
907
 * @example
908
 *
909
 * function Foo() {
910
 *   this.a = 1;
911
 *   this.b = 2;
912
 * }
913
 *
914
 * Foo.prototype.c = 3;
915
 *
916
 * _.keys(new Foo);
917
 * // => ['a', 'b'] (iteration order is not guaranteed)
918
 *
919
 * _.keys('hi');
920
 * // => ['0', '1']
921
 */
922
function keys(object) {
923
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
924
}
925

    
926
function createArrayIterator(coll) {
927
    var i = -1;
928
    var len = coll.length;
929
    return function next() {
930
        return ++i < len ? {value: coll[i], key: i} : null;
931
    }
932
}
933

    
934
function createES2015Iterator(iterator) {
935
    var i = -1;
936
    return function next() {
937
        var item = iterator.next();
938
        if (item.done)
939
            return null;
940
        i++;
941
        return {value: item.value, key: i};
942
    }
943
}
944

    
945
function createObjectIterator(obj) {
946
    var okeys = keys(obj);
947
    var i = -1;
948
    var len = okeys.length;
949
    return function next() {
950
        var key = okeys[++i];
951
        return i < len ? {value: obj[key], key: key} : null;
952
    };
953
}
954

    
955
function iterator(coll) {
956
    if (isArrayLike(coll)) {
957
        return createArrayIterator(coll);
958
    }
959

    
960
    var iterator = getIterator(coll);
961
    return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll);
962
}
963

    
964
function onlyOnce(fn) {
965
    return function() {
966
        if (fn === null) throw new Error("Callback was already called.");
967
        var callFn = fn;
968
        fn = null;
969
        callFn.apply(this, arguments);
970
    };
971
}
972

    
973
function _eachOfLimit(limit) {
974
    return function (obj, iteratee, callback) {
975
        callback = once(callback || noop);
976
        if (limit <= 0 || !obj) {
977
            return callback(null);
978
        }
979
        var nextElem = iterator(obj);
980
        var done = false;
981
        var running = 0;
982
        var looping = false;
983

    
984
        function iterateeCallback(err, value) {
985
            running -= 1;
986
            if (err) {
987
                done = true;
988
                callback(err);
989
            }
990
            else if (value === breakLoop || (done && running <= 0)) {
991
                done = true;
992
                return callback(null);
993
            }
994
            else if (!looping) {
995
                replenish();
996
            }
997
        }
998

    
999
        function replenish () {
1000
            looping = true;
1001
            while (running < limit && !done) {
1002
                var elem = nextElem();
1003
                if (elem === null) {
1004
                    done = true;
1005
                    if (running <= 0) {
1006
                        callback(null);
1007
                    }
1008
                    return;
1009
                }
1010
                running += 1;
1011
                iteratee(elem.value, elem.key, onlyOnce(iterateeCallback));
1012
            }
1013
            looping = false;
1014
        }
1015

    
1016
        replenish();
1017
    };
1018
}
1019

    
1020
/**
1021
 * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
1022
 * time.
1023
 *
1024
 * @name eachOfLimit
1025
 * @static
1026
 * @memberOf module:Collections
1027
 * @method
1028
 * @see [async.eachOf]{@link module:Collections.eachOf}
1029
 * @alias forEachOfLimit
1030
 * @category Collection
1031
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
1032
 * @param {number} limit - The maximum number of async operations at a time.
1033
 * @param {AsyncFunction} iteratee - An async function to apply to each
1034
 * item in `coll`. The `key` is the item's key, or index in the case of an
1035
 * array.
1036
 * Invoked with (item, key, callback).
1037
 * @param {Function} [callback] - A callback which is called when all
1038
 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
1039
 */
1040
function eachOfLimit(coll, limit, iteratee, callback) {
1041
    _eachOfLimit(limit)(coll, wrapAsync(iteratee), callback);
1042
}
1043

    
1044
function doLimit(fn, limit) {
1045
    return function (iterable, iteratee, callback) {
1046
        return fn(iterable, limit, iteratee, callback);
1047
    };
1048
}
1049

    
1050
// eachOf implementation optimized for array-likes
1051
function eachOfArrayLike(coll, iteratee, callback) {
1052
    callback = once(callback || noop);
1053
    var index = 0,
1054
        completed = 0,
1055
        length = coll.length;
1056
    if (length === 0) {
1057
        callback(null);
1058
    }
1059

    
1060
    function iteratorCallback(err, value) {
1061
        if (err) {
1062
            callback(err);
1063
        } else if ((++completed === length) || value === breakLoop) {
1064
            callback(null);
1065
        }
1066
    }
1067

    
1068
    for (; index < length; index++) {
1069
        iteratee(coll[index], index, onlyOnce(iteratorCallback));
1070
    }
1071
}
1072

    
1073
// a generic version of eachOf which can handle array, object, and iterator cases.
1074
var eachOfGeneric = doLimit(eachOfLimit, Infinity);
1075

    
1076
/**
1077
 * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument
1078
 * to the iteratee.
1079
 *
1080
 * @name eachOf
1081
 * @static
1082
 * @memberOf module:Collections
1083
 * @method
1084
 * @alias forEachOf
1085
 * @category Collection
1086
 * @see [async.each]{@link module:Collections.each}
1087
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
1088
 * @param {AsyncFunction} iteratee - A function to apply to each
1089
 * item in `coll`.
1090
 * The `key` is the item's key, or index in the case of an array.
1091
 * Invoked with (item, key, callback).
1092
 * @param {Function} [callback] - A callback which is called when all
1093
 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
1094
 * @example
1095
 *
1096
 * var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
1097
 * var configs = {};
1098
 *
1099
 * async.forEachOf(obj, function (value, key, callback) {
1100
 *     fs.readFile(__dirname + value, "utf8", function (err, data) {
1101
 *         if (err) return callback(err);
1102
 *         try {
1103
 *             configs[key] = JSON.parse(data);
1104
 *         } catch (e) {
1105
 *             return callback(e);
1106
 *         }
1107
 *         callback();
1108
 *     });
1109
 * }, function (err) {
1110
 *     if (err) console.error(err.message);
1111
 *     // configs is now a map of JSON data
1112
 *     doSomethingWith(configs);
1113
 * });
1114
 */
1115
var eachOf = function(coll, iteratee, callback) {
1116
    var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric;
1117
    eachOfImplementation(coll, wrapAsync(iteratee), callback);
1118
};
1119

    
1120
function doParallel(fn) {
1121
    return function (obj, iteratee, callback) {
1122
        return fn(eachOf, obj, wrapAsync(iteratee), callback);
1123
    };
1124
}
1125

    
1126
function _asyncMap(eachfn, arr, iteratee, callback) {
1127
    callback = callback || noop;
1128
    arr = arr || [];
1129
    var results = [];
1130
    var counter = 0;
1131
    var _iteratee = wrapAsync(iteratee);
1132

    
1133
    eachfn(arr, function (value, _, callback) {
1134
        var index = counter++;
1135
        _iteratee(value, function (err, v) {
1136
            results[index] = v;
1137
            callback(err);
1138
        });
1139
    }, function (err) {
1140
        callback(err, results);
1141
    });
1142
}
1143

    
1144
/**
1145
 * Produces a new collection of values by mapping each value in `coll` through
1146
 * the `iteratee` function. The `iteratee` is called with an item from `coll`
1147
 * and a callback for when it has finished processing. Each of these callback
1148
 * takes 2 arguments: an `error`, and the transformed item from `coll`. If
1149
 * `iteratee` passes an error to its callback, the main `callback` (for the
1150
 * `map` function) is immediately called with the error.
1151
 *
1152
 * Note, that since this function applies the `iteratee` to each item in
1153
 * parallel, there is no guarantee that the `iteratee` functions will complete
1154
 * in order. However, the results array will be in the same order as the
1155
 * original `coll`.
1156
 *
1157
 * If `map` is passed an Object, the results will be an Array.  The results
1158
 * will roughly be in the order of the original Objects' keys (but this can
1159
 * vary across JavaScript engines).
1160
 *
1161
 * @name map
1162
 * @static
1163
 * @memberOf module:Collections
1164
 * @method
1165
 * @category Collection
1166
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
1167
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
1168
 * `coll`.
1169
 * The iteratee should complete with the transformed item.
1170
 * Invoked with (item, callback).
1171
 * @param {Function} [callback] - A callback which is called when all `iteratee`
1172
 * functions have finished, or an error occurs. Results is an Array of the
1173
 * transformed items from the `coll`. Invoked with (err, results).
1174
 * @example
1175
 *
1176
 * async.map(['file1','file2','file3'], fs.stat, function(err, results) {
1177
 *     // results is now an array of stats for each file
1178
 * });
1179
 */
1180
var map = doParallel(_asyncMap);
1181

    
1182
/**
1183
 * Applies the provided arguments to each function in the array, calling
1184
 * `callback` after all functions have completed. If you only provide the first
1185
 * argument, `fns`, then it will return a function which lets you pass in the
1186
 * arguments as if it were a single function call. If more arguments are
1187
 * provided, `callback` is required while `args` is still optional.
1188
 *
1189
 * @name applyEach
1190
 * @static
1191
 * @memberOf module:ControlFlow
1192
 * @method
1193
 * @category Control Flow
1194
 * @param {Array|Iterable|Object} fns - A collection of {@link AsyncFunction}s
1195
 * to all call with the same arguments
1196
 * @param {...*} [args] - any number of separate arguments to pass to the
1197
 * function.
1198
 * @param {Function} [callback] - the final argument should be the callback,
1199
 * called when all functions have completed processing.
1200
 * @returns {Function} - If only the first argument, `fns`, is provided, it will
1201
 * return a function which lets you pass in the arguments as if it were a single
1202
 * function call. The signature is `(..args, callback)`. If invoked with any
1203
 * arguments, `callback` is required.
1204
 * @example
1205
 *
1206
 * async.applyEach([enableSearch, updateSchema], 'bucket', callback);
1207
 *
1208
 * // partial application example:
1209
 * async.each(
1210
 *     buckets,
1211
 *     async.applyEach([enableSearch, updateSchema]),
1212
 *     callback
1213
 * );
1214
 */
1215
var applyEach = applyEach$1(map);
1216

    
1217
function doParallelLimit(fn) {
1218
    return function (obj, limit, iteratee, callback) {
1219
        return fn(_eachOfLimit(limit), obj, wrapAsync(iteratee), callback);
1220
    };
1221
}
1222

    
1223
/**
1224
 * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time.
1225
 *
1226
 * @name mapLimit
1227
 * @static
1228
 * @memberOf module:Collections
1229
 * @method
1230
 * @see [async.map]{@link module:Collections.map}
1231
 * @category Collection
1232
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
1233
 * @param {number} limit - The maximum number of async operations at a time.
1234
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
1235
 * `coll`.
1236
 * The iteratee should complete with the transformed item.
1237
 * Invoked with (item, callback).
1238
 * @param {Function} [callback] - A callback which is called when all `iteratee`
1239
 * functions have finished, or an error occurs. Results is an array of the
1240
 * transformed items from the `coll`. Invoked with (err, results).
1241
 */
1242
var mapLimit = doParallelLimit(_asyncMap);
1243

    
1244
/**
1245
 * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time.
1246
 *
1247
 * @name mapSeries
1248
 * @static
1249
 * @memberOf module:Collections
1250
 * @method
1251
 * @see [async.map]{@link module:Collections.map}
1252
 * @category Collection
1253
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
1254
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
1255
 * `coll`.
1256
 * The iteratee should complete with the transformed item.
1257
 * Invoked with (item, callback).
1258
 * @param {Function} [callback] - A callback which is called when all `iteratee`
1259
 * functions have finished, or an error occurs. Results is an array of the
1260
 * transformed items from the `coll`. Invoked with (err, results).
1261
 */
1262
var mapSeries = doLimit(mapLimit, 1);
1263

    
1264
/**
1265
 * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time.
1266
 *
1267
 * @name applyEachSeries
1268
 * @static
1269
 * @memberOf module:ControlFlow
1270
 * @method
1271
 * @see [async.applyEach]{@link module:ControlFlow.applyEach}
1272
 * @category Control Flow
1273
 * @param {Array|Iterable|Object} fns - A collection of {@link AsyncFunction}s to all
1274
 * call with the same arguments
1275
 * @param {...*} [args] - any number of separate arguments to pass to the
1276
 * function.
1277
 * @param {Function} [callback] - the final argument should be the callback,
1278
 * called when all functions have completed processing.
1279
 * @returns {Function} - If only the first argument is provided, it will return
1280
 * a function which lets you pass in the arguments as if it were a single
1281
 * function call.
1282
 */
1283
var applyEachSeries = applyEach$1(mapSeries);
1284

    
1285
/**
1286
 * A specialized version of `_.forEach` for arrays without support for
1287
 * iteratee shorthands.
1288
 *
1289
 * @private
1290
 * @param {Array} [array] The array to iterate over.
1291
 * @param {Function} iteratee The function invoked per iteration.
1292
 * @returns {Array} Returns `array`.
1293
 */
1294
function arrayEach(array, iteratee) {
1295
  var index = -1,
1296
      length = array == null ? 0 : array.length;
1297

    
1298
  while (++index < length) {
1299
    if (iteratee(array[index], index, array) === false) {
1300
      break;
1301
    }
1302
  }
1303
  return array;
1304
}
1305

    
1306
/**
1307
 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
1308
 *
1309
 * @private
1310
 * @param {boolean} [fromRight] Specify iterating from right to left.
1311
 * @returns {Function} Returns the new base function.
1312
 */
1313
function createBaseFor(fromRight) {
1314
  return function(object, iteratee, keysFunc) {
1315
    var index = -1,
1316
        iterable = Object(object),
1317
        props = keysFunc(object),
1318
        length = props.length;
1319

    
1320
    while (length--) {
1321
      var key = props[fromRight ? length : ++index];
1322
      if (iteratee(iterable[key], key, iterable) === false) {
1323
        break;
1324
      }
1325
    }
1326
    return object;
1327
  };
1328
}
1329

    
1330
/**
1331
 * The base implementation of `baseForOwn` which iterates over `object`
1332
 * properties returned by `keysFunc` and invokes `iteratee` for each property.
1333
 * Iteratee functions may exit iteration early by explicitly returning `false`.
1334
 *
1335
 * @private
1336
 * @param {Object} object The object to iterate over.
1337
 * @param {Function} iteratee The function invoked per iteration.
1338
 * @param {Function} keysFunc The function to get the keys of `object`.
1339
 * @returns {Object} Returns `object`.
1340
 */
1341
var baseFor = createBaseFor();
1342

    
1343
/**
1344
 * The base implementation of `_.forOwn` without support for iteratee shorthands.
1345
 *
1346
 * @private
1347
 * @param {Object} object The object to iterate over.
1348
 * @param {Function} iteratee The function invoked per iteration.
1349
 * @returns {Object} Returns `object`.
1350
 */
1351
function baseForOwn(object, iteratee) {
1352
  return object && baseFor(object, iteratee, keys);
1353
}
1354

    
1355
/**
1356
 * The base implementation of `_.findIndex` and `_.findLastIndex` without
1357
 * support for iteratee shorthands.
1358
 *
1359
 * @private
1360
 * @param {Array} array The array to inspect.
1361
 * @param {Function} predicate The function invoked per iteration.
1362
 * @param {number} fromIndex The index to search from.
1363
 * @param {boolean} [fromRight] Specify iterating from right to left.
1364
 * @returns {number} Returns the index of the matched value, else `-1`.
1365
 */
1366
function baseFindIndex(array, predicate, fromIndex, fromRight) {
1367
  var length = array.length,
1368
      index = fromIndex + (fromRight ? 1 : -1);
1369

    
1370
  while ((fromRight ? index-- : ++index < length)) {
1371
    if (predicate(array[index], index, array)) {
1372
      return index;
1373
    }
1374
  }
1375
  return -1;
1376
}
1377

    
1378
/**
1379
 * The base implementation of `_.isNaN` without support for number objects.
1380
 *
1381
 * @private
1382
 * @param {*} value The value to check.
1383
 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
1384
 */
1385
function baseIsNaN(value) {
1386
  return value !== value;
1387
}
1388

    
1389
/**
1390
 * A specialized version of `_.indexOf` which performs strict equality
1391
 * comparisons of values, i.e. `===`.
1392
 *
1393
 * @private
1394
 * @param {Array} array The array to inspect.
1395
 * @param {*} value The value to search for.
1396
 * @param {number} fromIndex The index to search from.
1397
 * @returns {number} Returns the index of the matched value, else `-1`.
1398
 */
1399
function strictIndexOf(array, value, fromIndex) {
1400
  var index = fromIndex - 1,
1401
      length = array.length;
1402

    
1403
  while (++index < length) {
1404
    if (array[index] === value) {
1405
      return index;
1406
    }
1407
  }
1408
  return -1;
1409
}
1410

    
1411
/**
1412
 * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
1413
 *
1414
 * @private
1415
 * @param {Array} array The array to inspect.
1416
 * @param {*} value The value to search for.
1417
 * @param {number} fromIndex The index to search from.
1418
 * @returns {number} Returns the index of the matched value, else `-1`.
1419
 */
1420
function baseIndexOf(array, value, fromIndex) {
1421
  return value === value
1422
    ? strictIndexOf(array, value, fromIndex)
1423
    : baseFindIndex(array, baseIsNaN, fromIndex);
1424
}
1425

    
1426
/**
1427
 * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on
1428
 * their requirements. Each function can optionally depend on other functions
1429
 * being completed first, and each function is run as soon as its requirements
1430
 * are satisfied.
1431
 *
1432
 * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence
1433
 * will stop. Further tasks will not execute (so any other functions depending
1434
 * on it will not run), and the main `callback` is immediately called with the
1435
 * error.
1436
 *
1437
 * {@link AsyncFunction}s also receive an object containing the results of functions which
1438
 * have completed so far as the first argument, if they have dependencies. If a
1439
 * task function has no dependencies, it will only be passed a callback.
1440
 *
1441
 * @name auto
1442
 * @static
1443
 * @memberOf module:ControlFlow
1444
 * @method
1445
 * @category Control Flow
1446
 * @param {Object} tasks - An object. Each of its properties is either a
1447
 * function or an array of requirements, with the {@link AsyncFunction} itself the last item
1448
 * in the array. The object's key of a property serves as the name of the task
1449
 * defined by that property, i.e. can be used when specifying requirements for
1450
 * other tasks. The function receives one or two arguments:
1451
 * * a `results` object, containing the results of the previously executed
1452
 *   functions, only passed if the task has any dependencies,
1453
 * * a `callback(err, result)` function, which must be called when finished,
1454
 *   passing an `error` (which can be `null`) and the result of the function's
1455
 *   execution.
1456
 * @param {number} [concurrency=Infinity] - An optional `integer` for
1457
 * determining the maximum number of tasks that can be run in parallel. By
1458
 * default, as many as possible.
1459
 * @param {Function} [callback] - An optional callback which is called when all
1460
 * the tasks have been completed. It receives the `err` argument if any `tasks`
1461
 * pass an error to their callback. Results are always returned; however, if an
1462
 * error occurs, no further `tasks` will be performed, and the results object
1463
 * will only contain partial results. Invoked with (err, results).
1464
 * @returns undefined
1465
 * @example
1466
 *
1467
 * async.auto({
1468
 *     // this function will just be passed a callback
1469
 *     readData: async.apply(fs.readFile, 'data.txt', 'utf-8'),
1470
 *     showData: ['readData', function(results, cb) {
1471
 *         // results.readData is the file's contents
1472
 *         // ...
1473
 *     }]
1474
 * }, callback);
1475
 *
1476
 * async.auto({
1477
 *     get_data: function(callback) {
1478
 *         console.log('in get_data');
1479
 *         // async code to get some data
1480
 *         callback(null, 'data', 'converted to array');
1481
 *     },
1482
 *     make_folder: function(callback) {
1483
 *         console.log('in make_folder');
1484
 *         // async code to create a directory to store a file in
1485
 *         // this is run at the same time as getting the data
1486
 *         callback(null, 'folder');
1487
 *     },
1488
 *     write_file: ['get_data', 'make_folder', function(results, callback) {
1489
 *         console.log('in write_file', JSON.stringify(results));
1490
 *         // once there is some data and the directory exists,
1491
 *         // write the data to a file in the directory
1492
 *         callback(null, 'filename');
1493
 *     }],
1494
 *     email_link: ['write_file', function(results, callback) {
1495
 *         console.log('in email_link', JSON.stringify(results));
1496
 *         // once the file is written let's email a link to it...
1497
 *         // results.write_file contains the filename returned by write_file.
1498
 *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
1499
 *     }]
1500
 * }, function(err, results) {
1501
 *     console.log('err = ', err);
1502
 *     console.log('results = ', results);
1503
 * });
1504
 */
1505
var auto = function (tasks, concurrency, callback) {
1506
    if (typeof concurrency === 'function') {
1507
        // concurrency is optional, shift the args.
1508
        callback = concurrency;
1509
        concurrency = null;
1510
    }
1511
    callback = once(callback || noop);
1512
    var keys$$1 = keys(tasks);
1513
    var numTasks = keys$$1.length;
1514
    if (!numTasks) {
1515
        return callback(null);
1516
    }
1517
    if (!concurrency) {
1518
        concurrency = numTasks;
1519
    }
1520

    
1521
    var results = {};
1522
    var runningTasks = 0;
1523
    var hasError = false;
1524

    
1525
    var listeners = Object.create(null);
1526

    
1527
    var readyTasks = [];
1528

    
1529
    // for cycle detection:
1530
    var readyToCheck = []; // tasks that have been identified as reachable
1531
    // without the possibility of returning to an ancestor task
1532
    var uncheckedDependencies = {};
1533

    
1534
    baseForOwn(tasks, function (task, key) {
1535
        if (!isArray(task)) {
1536
            // no dependencies
1537
            enqueueTask(key, [task]);
1538
            readyToCheck.push(key);
1539
            return;
1540
        }
1541

    
1542
        var dependencies = task.slice(0, task.length - 1);
1543
        var remainingDependencies = dependencies.length;
1544
        if (remainingDependencies === 0) {
1545
            enqueueTask(key, task);
1546
            readyToCheck.push(key);
1547
            return;
1548
        }
1549
        uncheckedDependencies[key] = remainingDependencies;
1550

    
1551
        arrayEach(dependencies, function (dependencyName) {
1552
            if (!tasks[dependencyName]) {
1553
                throw new Error('async.auto task `' + key +
1554
                    '` has a non-existent dependency `' +
1555
                    dependencyName + '` in ' +
1556
                    dependencies.join(', '));
1557
            }
1558
            addListener(dependencyName, function () {
1559
                remainingDependencies--;
1560
                if (remainingDependencies === 0) {
1561
                    enqueueTask(key, task);
1562
                }
1563
            });
1564
        });
1565
    });
1566

    
1567
    checkForDeadlocks();
1568
    processQueue();
1569

    
1570
    function enqueueTask(key, task) {
1571
        readyTasks.push(function () {
1572
            runTask(key, task);
1573
        });
1574
    }
1575

    
1576
    function processQueue() {
1577
        if (readyTasks.length === 0 && runningTasks === 0) {
1578
            return callback(null, results);
1579
        }
1580
        while(readyTasks.length && runningTasks < concurrency) {
1581
            var run = readyTasks.shift();
1582
            run();
1583
        }
1584

    
1585
    }
1586

    
1587
    function addListener(taskName, fn) {
1588
        var taskListeners = listeners[taskName];
1589
        if (!taskListeners) {
1590
            taskListeners = listeners[taskName] = [];
1591
        }
1592

    
1593
        taskListeners.push(fn);
1594
    }
1595

    
1596
    function taskComplete(taskName) {
1597
        var taskListeners = listeners[taskName] || [];
1598
        arrayEach(taskListeners, function (fn) {
1599
            fn();
1600
        });
1601
        processQueue();
1602
    }
1603

    
1604

    
1605
    function runTask(key, task) {
1606
        if (hasError) return;
1607

    
1608
        var taskCallback = onlyOnce(function(err, result) {
1609
            runningTasks--;
1610
            if (arguments.length > 2) {
1611
                result = slice(arguments, 1);
1612
            }
1613
            if (err) {
1614
                var safeResults = {};
1615
                baseForOwn(results, function(val, rkey) {
1616
                    safeResults[rkey] = val;
1617
                });
1618
                safeResults[key] = result;
1619
                hasError = true;
1620
                listeners = Object.create(null);
1621

    
1622
                callback(err, safeResults);
1623
            } else {
1624
                results[key] = result;
1625
                taskComplete(key);
1626
            }
1627
        });
1628

    
1629
        runningTasks++;
1630
        var taskFn = wrapAsync(task[task.length - 1]);
1631
        if (task.length > 1) {
1632
            taskFn(results, taskCallback);
1633
        } else {
1634
            taskFn(taskCallback);
1635
        }
1636
    }
1637

    
1638
    function checkForDeadlocks() {
1639
        // Kahn's algorithm
1640
        // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
1641
        // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html
1642
        var currentTask;
1643
        var counter = 0;
1644
        while (readyToCheck.length) {
1645
            currentTask = readyToCheck.pop();
1646
            counter++;
1647
            arrayEach(getDependents(currentTask), function (dependent) {
1648
                if (--uncheckedDependencies[dependent] === 0) {
1649
                    readyToCheck.push(dependent);
1650
                }
1651
            });
1652
        }
1653

    
1654
        if (counter !== numTasks) {
1655
            throw new Error(
1656
                'async.auto cannot execute tasks due to a recursive dependency'
1657
            );
1658
        }
1659
    }
1660

    
1661
    function getDependents(taskName) {
1662
        var result = [];
1663
        baseForOwn(tasks, function (task, key) {
1664
            if (isArray(task) && baseIndexOf(task, taskName, 0) >= 0) {
1665
                result.push(key);
1666
            }
1667
        });
1668
        return result;
1669
    }
1670
};
1671

    
1672
/**
1673
 * A specialized version of `_.map` for arrays without support for iteratee
1674
 * shorthands.
1675
 *
1676
 * @private
1677
 * @param {Array} [array] The array to iterate over.
1678
 * @param {Function} iteratee The function invoked per iteration.
1679
 * @returns {Array} Returns the new mapped array.
1680
 */
1681
function arrayMap(array, iteratee) {
1682
  var index = -1,
1683
      length = array == null ? 0 : array.length,
1684
      result = Array(length);
1685

    
1686
  while (++index < length) {
1687
    result[index] = iteratee(array[index], index, array);
1688
  }
1689
  return result;
1690
}
1691

    
1692
/** `Object#toString` result references. */
1693
var symbolTag = '[object Symbol]';
1694

    
1695
/**
1696
 * Checks if `value` is classified as a `Symbol` primitive or object.
1697
 *
1698
 * @static
1699
 * @memberOf _
1700
 * @since 4.0.0
1701
 * @category Lang
1702
 * @param {*} value The value to check.
1703
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
1704
 * @example
1705
 *
1706
 * _.isSymbol(Symbol.iterator);
1707
 * // => true
1708
 *
1709
 * _.isSymbol('abc');
1710
 * // => false
1711
 */
1712
function isSymbol(value) {
1713
  return typeof value == 'symbol' ||
1714
    (isObjectLike(value) && baseGetTag(value) == symbolTag);
1715
}
1716

    
1717
/** Used as references for various `Number` constants. */
1718
var INFINITY = 1 / 0;
1719

    
1720
/** Used to convert symbols to primitives and strings. */
1721
var symbolProto = Symbol$1 ? Symbol$1.prototype : undefined;
1722
var symbolToString = symbolProto ? symbolProto.toString : undefined;
1723

    
1724
/**
1725
 * The base implementation of `_.toString` which doesn't convert nullish
1726
 * values to empty strings.
1727
 *
1728
 * @private
1729
 * @param {*} value The value to process.
1730
 * @returns {string} Returns the string.
1731
 */
1732
function baseToString(value) {
1733
  // Exit early for strings to avoid a performance hit in some environments.
1734
  if (typeof value == 'string') {
1735
    return value;
1736
  }
1737
  if (isArray(value)) {
1738
    // Recursively convert values (susceptible to call stack limits).
1739
    return arrayMap(value, baseToString) + '';
1740
  }
1741
  if (isSymbol(value)) {
1742
    return symbolToString ? symbolToString.call(value) : '';
1743
  }
1744
  var result = (value + '');
1745
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
1746
}
1747

    
1748
/**
1749
 * The base implementation of `_.slice` without an iteratee call guard.
1750
 *
1751
 * @private
1752
 * @param {Array} array The array to slice.
1753
 * @param {number} [start=0] The start position.
1754
 * @param {number} [end=array.length] The end position.
1755
 * @returns {Array} Returns the slice of `array`.
1756
 */
1757
function baseSlice(array, start, end) {
1758
  var index = -1,
1759
      length = array.length;
1760

    
1761
  if (start < 0) {
1762
    start = -start > length ? 0 : (length + start);
1763
  }
1764
  end = end > length ? length : end;
1765
  if (end < 0) {
1766
    end += length;
1767
  }
1768
  length = start > end ? 0 : ((end - start) >>> 0);
1769
  start >>>= 0;
1770

    
1771
  var result = Array(length);
1772
  while (++index < length) {
1773
    result[index] = array[index + start];
1774
  }
1775
  return result;
1776
}
1777

    
1778
/**
1779
 * Casts `array` to a slice if it's needed.
1780
 *
1781
 * @private
1782
 * @param {Array} array The array to inspect.
1783
 * @param {number} start The start position.
1784
 * @param {number} [end=array.length] The end position.
1785
 * @returns {Array} Returns the cast slice.
1786
 */
1787
function castSlice(array, start, end) {
1788
  var length = array.length;
1789
  end = end === undefined ? length : end;
1790
  return (!start && end >= length) ? array : baseSlice(array, start, end);
1791
}
1792

    
1793
/**
1794
 * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
1795
 * that is not found in the character symbols.
1796
 *
1797
 * @private
1798
 * @param {Array} strSymbols The string symbols to inspect.
1799
 * @param {Array} chrSymbols The character symbols to find.
1800
 * @returns {number} Returns the index of the last unmatched string symbol.
1801
 */
1802
function charsEndIndex(strSymbols, chrSymbols) {
1803
  var index = strSymbols.length;
1804

    
1805
  while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1806
  return index;
1807
}
1808

    
1809
/**
1810
 * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
1811
 * that is not found in the character symbols.
1812
 *
1813
 * @private
1814
 * @param {Array} strSymbols The string symbols to inspect.
1815
 * @param {Array} chrSymbols The character symbols to find.
1816
 * @returns {number} Returns the index of the first unmatched string symbol.
1817
 */
1818
function charsStartIndex(strSymbols, chrSymbols) {
1819
  var index = -1,
1820
      length = strSymbols.length;
1821

    
1822
  while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1823
  return index;
1824
}
1825

    
1826
/**
1827
 * Converts an ASCII `string` to an array.
1828
 *
1829
 * @private
1830
 * @param {string} string The string to convert.
1831
 * @returns {Array} Returns the converted array.
1832
 */
1833
function asciiToArray(string) {
1834
  return string.split('');
1835
}
1836

    
1837
/** Used to compose unicode character classes. */
1838
var rsAstralRange = '\\ud800-\\udfff';
1839
var rsComboMarksRange = '\\u0300-\\u036f';
1840
var reComboHalfMarksRange = '\\ufe20-\\ufe2f';
1841
var rsComboSymbolsRange = '\\u20d0-\\u20ff';
1842
var rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;
1843
var rsVarRange = '\\ufe0e\\ufe0f';
1844

    
1845
/** Used to compose unicode capture groups. */
1846
var rsZWJ = '\\u200d';
1847

    
1848
/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
1849
var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange  + rsComboRange + rsVarRange + ']');
1850

    
1851
/**
1852
 * Checks if `string` contains Unicode symbols.
1853
 *
1854
 * @private
1855
 * @param {string} string The string to inspect.
1856
 * @returns {boolean} Returns `true` if a symbol is found, else `false`.
1857
 */
1858
function hasUnicode(string) {
1859
  return reHasUnicode.test(string);
1860
}
1861

    
1862
/** Used to compose unicode character classes. */
1863
var rsAstralRange$1 = '\\ud800-\\udfff';
1864
var rsComboMarksRange$1 = '\\u0300-\\u036f';
1865
var reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f';
1866
var rsComboSymbolsRange$1 = '\\u20d0-\\u20ff';
1867
var rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1;
1868
var rsVarRange$1 = '\\ufe0e\\ufe0f';
1869

    
1870
/** Used to compose unicode capture groups. */
1871
var rsAstral = '[' + rsAstralRange$1 + ']';
1872
var rsCombo = '[' + rsComboRange$1 + ']';
1873
var rsFitz = '\\ud83c[\\udffb-\\udfff]';
1874
var rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')';
1875
var rsNonAstral = '[^' + rsAstralRange$1 + ']';
1876
var rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}';
1877
var rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]';
1878
var rsZWJ$1 = '\\u200d';
1879

    
1880
/** Used to compose unicode regexes. */
1881
var reOptMod = rsModifier + '?';
1882
var rsOptVar = '[' + rsVarRange$1 + ']?';
1883
var rsOptJoin = '(?:' + rsZWJ$1 + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*';
1884
var rsSeq = rsOptVar + reOptMod + rsOptJoin;
1885
var rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
1886

    
1887
/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
1888
var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
1889

    
1890
/**
1891
 * Converts a Unicode `string` to an array.
1892
 *
1893
 * @private
1894
 * @param {string} string The string to convert.
1895
 * @returns {Array} Returns the converted array.
1896
 */
1897
function unicodeToArray(string) {
1898
  return string.match(reUnicode) || [];
1899
}
1900

    
1901
/**
1902
 * Converts `string` to an array.
1903
 *
1904
 * @private
1905
 * @param {string} string The string to convert.
1906
 * @returns {Array} Returns the converted array.
1907
 */
1908
function stringToArray(string) {
1909
  return hasUnicode(string)
1910
    ? unicodeToArray(string)
1911
    : asciiToArray(string);
1912
}
1913

    
1914
/**
1915
 * Converts `value` to a string. An empty string is returned for `null`
1916
 * and `undefined` values. The sign of `-0` is preserved.
1917
 *
1918
 * @static
1919
 * @memberOf _
1920
 * @since 4.0.0
1921
 * @category Lang
1922
 * @param {*} value The value to convert.
1923
 * @returns {string} Returns the converted string.
1924
 * @example
1925
 *
1926
 * _.toString(null);
1927
 * // => ''
1928
 *
1929
 * _.toString(-0);
1930
 * // => '-0'
1931
 *
1932
 * _.toString([1, 2, 3]);
1933
 * // => '1,2,3'
1934
 */
1935
function toString(value) {
1936
  return value == null ? '' : baseToString(value);
1937
}
1938

    
1939
/** Used to match leading and trailing whitespace. */
1940
var reTrim = /^\s+|\s+$/g;
1941

    
1942
/**
1943
 * Removes leading and trailing whitespace or specified characters from `string`.
1944
 *
1945
 * @static
1946
 * @memberOf _
1947
 * @since 3.0.0
1948
 * @category String
1949
 * @param {string} [string=''] The string to trim.
1950
 * @param {string} [chars=whitespace] The characters to trim.
1951
 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
1952
 * @returns {string} Returns the trimmed string.
1953
 * @example
1954
 *
1955
 * _.trim('  abc  ');
1956
 * // => 'abc'
1957
 *
1958
 * _.trim('-_-abc-_-', '_-');
1959
 * // => 'abc'
1960
 *
1961
 * _.map(['  foo  ', '  bar  '], _.trim);
1962
 * // => ['foo', 'bar']
1963
 */
1964
function trim(string, chars, guard) {
1965
  string = toString(string);
1966
  if (string && (guard || chars === undefined)) {
1967
    return string.replace(reTrim, '');
1968
  }
1969
  if (!string || !(chars = baseToString(chars))) {
1970
    return string;
1971
  }
1972
  var strSymbols = stringToArray(string),
1973
      chrSymbols = stringToArray(chars),
1974
      start = charsStartIndex(strSymbols, chrSymbols),
1975
      end = charsEndIndex(strSymbols, chrSymbols) + 1;
1976

    
1977
  return castSlice(strSymbols, start, end).join('');
1978
}
1979

    
1980
var FN_ARGS = /^(?:async\s+)?(function)?\s*[^\(]*\(\s*([^\)]*)\)/m;
1981
var FN_ARG_SPLIT = /,/;
1982
var FN_ARG = /(=.+)?(\s*)$/;
1983
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
1984

    
1985
function parseParams(func) {
1986
    func = func.toString().replace(STRIP_COMMENTS, '');
1987
    func = func.match(FN_ARGS)[2].replace(' ', '');
1988
    func = func ? func.split(FN_ARG_SPLIT) : [];
1989
    func = func.map(function (arg){
1990
        return trim(arg.replace(FN_ARG, ''));
1991
    });
1992
    return func;
1993
}
1994

    
1995
/**
1996
 * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent
1997
 * tasks are specified as parameters to the function, after the usual callback
1998
 * parameter, with the parameter names matching the names of the tasks it
1999
 * depends on. This can provide even more readable task graphs which can be
2000
 * easier to maintain.
2001
 *
2002
 * If a final callback is specified, the task results are similarly injected,
2003
 * specified as named parameters after the initial error parameter.
2004
 *
2005
 * The autoInject function is purely syntactic sugar and its semantics are
2006
 * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}.
2007
 *
2008
 * @name autoInject
2009
 * @static
2010
 * @memberOf module:ControlFlow
2011
 * @method
2012
 * @see [async.auto]{@link module:ControlFlow.auto}
2013
 * @category Control Flow
2014
 * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of
2015
 * the form 'func([dependencies...], callback). The object's key of a property
2016
 * serves as the name of the task defined by that property, i.e. can be used
2017
 * when specifying requirements for other tasks.
2018
 * * The `callback` parameter is a `callback(err, result)` which must be called
2019
 *   when finished, passing an `error` (which can be `null`) and the result of
2020
 *   the function's execution. The remaining parameters name other tasks on
2021
 *   which the task is dependent, and the results from those tasks are the
2022
 *   arguments of those parameters.
2023
 * @param {Function} [callback] - An optional callback which is called when all
2024
 * the tasks have been completed. It receives the `err` argument if any `tasks`
2025
 * pass an error to their callback, and a `results` object with any completed
2026
 * task results, similar to `auto`.
2027
 * @example
2028
 *
2029
 * //  The example from `auto` can be rewritten as follows:
2030
 * async.autoInject({
2031
 *     get_data: function(callback) {
2032
 *         // async code to get some data
2033
 *         callback(null, 'data', 'converted to array');
2034
 *     },
2035
 *     make_folder: function(callback) {
2036
 *         // async code to create a directory to store a file in
2037
 *         // this is run at the same time as getting the data
2038
 *         callback(null, 'folder');
2039
 *     },
2040
 *     write_file: function(get_data, make_folder, callback) {
2041
 *         // once there is some data and the directory exists,
2042
 *         // write the data to a file in the directory
2043
 *         callback(null, 'filename');
2044
 *     },
2045
 *     email_link: function(write_file, callback) {
2046
 *         // once the file is written let's email a link to it...
2047
 *         // write_file contains the filename returned by write_file.
2048
 *         callback(null, {'file':write_file, 'email':'user@example.com'});
2049
 *     }
2050
 * }, function(err, results) {
2051
 *     console.log('err = ', err);
2052
 *     console.log('email_link = ', results.email_link);
2053
 * });
2054
 *
2055
 * // If you are using a JS minifier that mangles parameter names, `autoInject`
2056
 * // will not work with plain functions, since the parameter names will be
2057
 * // collapsed to a single letter identifier.  To work around this, you can
2058
 * // explicitly specify the names of the parameters your task function needs
2059
 * // in an array, similar to Angular.js dependency injection.
2060
 *
2061
 * // This still has an advantage over plain `auto`, since the results a task
2062
 * // depends on are still spread into arguments.
2063
 * async.autoInject({
2064
 *     //...
2065
 *     write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) {
2066
 *         callback(null, 'filename');
2067
 *     }],
2068
 *     email_link: ['write_file', function(write_file, callback) {
2069
 *         callback(null, {'file':write_file, 'email':'user@example.com'});
2070
 *     }]
2071
 *     //...
2072
 * }, function(err, results) {
2073
 *     console.log('err = ', err);
2074
 *     console.log('email_link = ', results.email_link);
2075
 * });
2076
 */
2077
function autoInject(tasks, callback) {
2078
    var newTasks = {};
2079

    
2080
    baseForOwn(tasks, function (taskFn, key) {
2081
        var params;
2082
        var fnIsAsync = isAsync(taskFn);
2083
        var hasNoDeps =
2084
            (!fnIsAsync && taskFn.length === 1) ||
2085
            (fnIsAsync && taskFn.length === 0);
2086

    
2087
        if (isArray(taskFn)) {
2088
            params = taskFn.slice(0, -1);
2089
            taskFn = taskFn[taskFn.length - 1];
2090

    
2091
            newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn);
2092
        } else if (hasNoDeps) {
2093
            // no dependencies, use the function as-is
2094
            newTasks[key] = taskFn;
2095
        } else {
2096
            params = parseParams(taskFn);
2097
            if (taskFn.length === 0 && !fnIsAsync && params.length === 0) {
2098
                throw new Error("autoInject task functions require explicit parameters.");
2099
            }
2100

    
2101
            // remove callback param
2102
            if (!fnIsAsync) params.pop();
2103

    
2104
            newTasks[key] = params.concat(newTask);
2105
        }
2106

    
2107
        function newTask(results, taskCb) {
2108
            var newArgs = arrayMap(params, function (name) {
2109
                return results[name];
2110
            });
2111
            newArgs.push(taskCb);
2112
            wrapAsync(taskFn).apply(null, newArgs);
2113
        }
2114
    });
2115

    
2116
    auto(newTasks, callback);
2117
}
2118

    
2119
// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation
2120
// used for queues. This implementation assumes that the node provided by the user can be modified
2121
// to adjust the next and last properties. We implement only the minimal functionality
2122
// for queue support.
2123
function DLL() {
2124
    this.head = this.tail = null;
2125
    this.length = 0;
2126
}
2127

    
2128
function setInitial(dll, node) {
2129
    dll.length = 1;
2130
    dll.head = dll.tail = node;
2131
}
2132

    
2133
DLL.prototype.removeLink = function(node) {
2134
    if (node.prev) node.prev.next = node.next;
2135
    else this.head = node.next;
2136
    if (node.next) node.next.prev = node.prev;
2137
    else this.tail = node.prev;
2138

    
2139
    node.prev = node.next = null;
2140
    this.length -= 1;
2141
    return node;
2142
};
2143

    
2144
DLL.prototype.empty = function () {
2145
    while(this.head) this.shift();
2146
    return this;
2147
};
2148

    
2149
DLL.prototype.insertAfter = function(node, newNode) {
2150
    newNode.prev = node;
2151
    newNode.next = node.next;
2152
    if (node.next) node.next.prev = newNode;
2153
    else this.tail = newNode;
2154
    node.next = newNode;
2155
    this.length += 1;
2156
};
2157

    
2158
DLL.prototype.insertBefore = function(node, newNode) {
2159
    newNode.prev = node.prev;
2160
    newNode.next = node;
2161
    if (node.prev) node.prev.next = newNode;
2162
    else this.head = newNode;
2163
    node.prev = newNode;
2164
    this.length += 1;
2165
};
2166

    
2167
DLL.prototype.unshift = function(node) {
2168
    if (this.head) this.insertBefore(this.head, node);
2169
    else setInitial(this, node);
2170
};
2171

    
2172
DLL.prototype.push = function(node) {
2173
    if (this.tail) this.insertAfter(this.tail, node);
2174
    else setInitial(this, node);
2175
};
2176

    
2177
DLL.prototype.shift = function() {
2178
    return this.head && this.removeLink(this.head);
2179
};
2180

    
2181
DLL.prototype.pop = function() {
2182
    return this.tail && this.removeLink(this.tail);
2183
};
2184

    
2185
DLL.prototype.toArray = function () {
2186
    var arr = Array(this.length);
2187
    var curr = this.head;
2188
    for(var idx = 0; idx < this.length; idx++) {
2189
        arr[idx] = curr.data;
2190
        curr = curr.next;
2191
    }
2192
    return arr;
2193
};
2194

    
2195
DLL.prototype.remove = function (testFn) {
2196
    var curr = this.head;
2197
    while(!!curr) {
2198
        var next = curr.next;
2199
        if (testFn(curr)) {
2200
            this.removeLink(curr);
2201
        }
2202
        curr = next;
2203
    }
2204
    return this;
2205
};
2206

    
2207
function queue(worker, concurrency, payload) {
2208
    if (concurrency == null) {
2209
        concurrency = 1;
2210
    }
2211
    else if(concurrency === 0) {
2212
        throw new Error('Concurrency must not be zero');
2213
    }
2214

    
2215
    var _worker = wrapAsync(worker);
2216
    var numRunning = 0;
2217
    var workersList = [];
2218

    
2219
    var processingScheduled = false;
2220
    function _insert(data, insertAtFront, callback) {
2221
        if (callback != null && typeof callback !== 'function') {
2222
            throw new Error('task callback must be a function');
2223
        }
2224
        q.started = true;
2225
        if (!isArray(data)) {
2226
            data = [data];
2227
        }
2228
        if (data.length === 0 && q.idle()) {
2229
            // call drain immediately if there are no tasks
2230
            return setImmediate$1(function() {
2231
                q.drain();
2232
            });
2233
        }
2234

    
2235
        for (var i = 0, l = data.length; i < l; i++) {
2236
            var item = {
2237
                data: data[i],
2238
                callback: callback || noop
2239
            };
2240

    
2241
            if (insertAtFront) {
2242
                q._tasks.unshift(item);
2243
            } else {
2244
                q._tasks.push(item);
2245
            }
2246
        }
2247

    
2248
        if (!processingScheduled) {
2249
            processingScheduled = true;
2250
            setImmediate$1(function() {
2251
                processingScheduled = false;
2252
                q.process();
2253
            });
2254
        }
2255
    }
2256

    
2257
    function _next(tasks) {
2258
        return function(err){
2259
            numRunning -= 1;
2260

    
2261
            for (var i = 0, l = tasks.length; i < l; i++) {
2262
                var task = tasks[i];
2263

    
2264
                var index = baseIndexOf(workersList, task, 0);
2265
                if (index === 0) {
2266
                    workersList.shift();
2267
                } else if (index > 0) {
2268
                    workersList.splice(index, 1);
2269
                }
2270

    
2271
                task.callback.apply(task, arguments);
2272

    
2273
                if (err != null) {
2274
                    q.error(err, task.data);
2275
                }
2276
            }
2277

    
2278
            if (numRunning <= (q.concurrency - q.buffer) ) {
2279
                q.unsaturated();
2280
            }
2281

    
2282
            if (q.idle()) {
2283
                q.drain();
2284
            }
2285
            q.process();
2286
        };
2287
    }
2288

    
2289
    var isProcessing = false;
2290
    var q = {
2291
        _tasks: new DLL(),
2292
        concurrency: concurrency,
2293
        payload: payload,
2294
        saturated: noop,
2295
        unsaturated:noop,
2296
        buffer: concurrency / 4,
2297
        empty: noop,
2298
        drain: noop,
2299
        error: noop,
2300
        started: false,
2301
        paused: false,
2302
        push: function (data, callback) {
2303
            _insert(data, false, callback);
2304
        },
2305
        kill: function () {
2306
            q.drain = noop;
2307
            q._tasks.empty();
2308
        },
2309
        unshift: function (data, callback) {
2310
            _insert(data, true, callback);
2311
        },
2312
        remove: function (testFn) {
2313
            q._tasks.remove(testFn);
2314
        },
2315
        process: function () {
2316
            // Avoid trying to start too many processing operations. This can occur
2317
            // when callbacks resolve synchronously (#1267).
2318
            if (isProcessing) {
2319
                return;
2320
            }
2321
            isProcessing = true;
2322
            while(!q.paused && numRunning < q.concurrency && q._tasks.length){
2323
                var tasks = [], data = [];
2324
                var l = q._tasks.length;
2325
                if (q.payload) l = Math.min(l, q.payload);
2326
                for (var i = 0; i < l; i++) {
2327
                    var node = q._tasks.shift();
2328
                    tasks.push(node);
2329
                    workersList.push(node);
2330
                    data.push(node.data);
2331
                }
2332

    
2333
                numRunning += 1;
2334

    
2335
                if (q._tasks.length === 0) {
2336
                    q.empty();
2337
                }
2338

    
2339
                if (numRunning === q.concurrency) {
2340
                    q.saturated();
2341
                }
2342

    
2343
                var cb = onlyOnce(_next(tasks));
2344
                _worker(data, cb);
2345
            }
2346
            isProcessing = false;
2347
        },
2348
        length: function () {
2349
            return q._tasks.length;
2350
        },
2351
        running: function () {
2352
            return numRunning;
2353
        },
2354
        workersList: function () {
2355
            return workersList;
2356
        },
2357
        idle: function() {
2358
            return q._tasks.length + numRunning === 0;
2359
        },
2360
        pause: function () {
2361
            q.paused = true;
2362
        },
2363
        resume: function () {
2364
            if (q.paused === false) { return; }
2365
            q.paused = false;
2366
            setImmediate$1(q.process);
2367
        }
2368
    };
2369
    return q;
2370
}
2371

    
2372
/**
2373
 * A cargo of tasks for the worker function to complete. Cargo inherits all of
2374
 * the same methods and event callbacks as [`queue`]{@link module:ControlFlow.queue}.
2375
 * @typedef {Object} CargoObject
2376
 * @memberOf module:ControlFlow
2377
 * @property {Function} length - A function returning the number of items
2378
 * waiting to be processed. Invoke like `cargo.length()`.
2379
 * @property {number} payload - An `integer` for determining how many tasks
2380
 * should be process per round. This property can be changed after a `cargo` is
2381
 * created to alter the payload on-the-fly.
2382
 * @property {Function} push - Adds `task` to the `queue`. The callback is
2383
 * called once the `worker` has finished processing the task. Instead of a
2384
 * single task, an array of `tasks` can be submitted. The respective callback is
2385
 * used for every task in the list. Invoke like `cargo.push(task, [callback])`.
2386
 * @property {Function} saturated - A callback that is called when the
2387
 * `queue.length()` hits the concurrency and further tasks will be queued.
2388
 * @property {Function} empty - A callback that is called when the last item
2389
 * from the `queue` is given to a `worker`.
2390
 * @property {Function} drain - A callback that is called when the last item
2391
 * from the `queue` has returned from the `worker`.
2392
 * @property {Function} idle - a function returning false if there are items
2393
 * waiting or being processed, or true if not. Invoke like `cargo.idle()`.
2394
 * @property {Function} pause - a function that pauses the processing of tasks
2395
 * until `resume()` is called. Invoke like `cargo.pause()`.
2396
 * @property {Function} resume - a function that resumes the processing of
2397
 * queued tasks when the queue is paused. Invoke like `cargo.resume()`.
2398
 * @property {Function} kill - a function that removes the `drain` callback and
2399
 * empties remaining tasks from the queue forcing it to go idle. Invoke like `cargo.kill()`.
2400
 */
2401

    
2402
/**
2403
 * Creates a `cargo` object with the specified payload. Tasks added to the
2404
 * cargo will be processed altogether (up to the `payload` limit). If the
2405
 * `worker` is in progress, the task is queued until it becomes available. Once
2406
 * the `worker` has completed some tasks, each callback of those tasks is
2407
 * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
2408
 * for how `cargo` and `queue` work.
2409
 *
2410
 * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
2411
 * at a time, cargo passes an array of tasks to a single worker, repeating
2412
 * when the worker is finished.
2413
 *
2414
 * @name cargo
2415
 * @static
2416
 * @memberOf module:ControlFlow
2417
 * @method
2418
 * @see [async.queue]{@link module:ControlFlow.queue}
2419
 * @category Control Flow
2420
 * @param {AsyncFunction} worker - An asynchronous function for processing an array
2421
 * of queued tasks. Invoked with `(tasks, callback)`.
2422
 * @param {number} [payload=Infinity] - An optional `integer` for determining
2423
 * how many tasks should be processed per round; if omitted, the default is
2424
 * unlimited.
2425
 * @returns {module:ControlFlow.CargoObject} A cargo object to manage the tasks. Callbacks can
2426
 * attached as certain properties to listen for specific events during the
2427
 * lifecycle of the cargo and inner queue.
2428
 * @example
2429
 *
2430
 * // create a cargo object with payload 2
2431
 * var cargo = async.cargo(function(tasks, callback) {
2432
 *     for (var i=0; i<tasks.length; i++) {
2433
 *         console.log('hello ' + tasks[i].name);
2434
 *     }
2435
 *     callback();
2436
 * }, 2);
2437
 *
2438
 * // add some items
2439
 * cargo.push({name: 'foo'}, function(err) {
2440
 *     console.log('finished processing foo');
2441
 * });
2442
 * cargo.push({name: 'bar'}, function(err) {
2443
 *     console.log('finished processing bar');
2444
 * });
2445
 * cargo.push({name: 'baz'}, function(err) {
2446
 *     console.log('finished processing baz');
2447
 * });
2448
 */
2449
function cargo(worker, payload) {
2450
    return queue(worker, 1, payload);
2451
}
2452

    
2453
/**
2454
 * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
2455
 *
2456
 * @name eachOfSeries
2457
 * @static
2458
 * @memberOf module:Collections
2459
 * @method
2460
 * @see [async.eachOf]{@link module:Collections.eachOf}
2461
 * @alias forEachOfSeries
2462
 * @category Collection
2463
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2464
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
2465
 * `coll`.
2466
 * Invoked with (item, key, callback).
2467
 * @param {Function} [callback] - A callback which is called when all `iteratee`
2468
 * functions have finished, or an error occurs. Invoked with (err).
2469
 */
2470
var eachOfSeries = doLimit(eachOfLimit, 1);
2471

    
2472
/**
2473
 * Reduces `coll` into a single value using an async `iteratee` to return each
2474
 * successive step. `memo` is the initial state of the reduction. This function
2475
 * only operates in series.
2476
 *
2477
 * For performance reasons, it may make sense to split a call to this function
2478
 * into a parallel map, and then use the normal `Array.prototype.reduce` on the
2479
 * results. This function is for situations where each step in the reduction
2480
 * needs to be async; if you can get the data before reducing it, then it's
2481
 * probably a good idea to do so.
2482
 *
2483
 * @name reduce
2484
 * @static
2485
 * @memberOf module:Collections
2486
 * @method
2487
 * @alias inject
2488
 * @alias foldl
2489
 * @category Collection
2490
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2491
 * @param {*} memo - The initial state of the reduction.
2492
 * @param {AsyncFunction} iteratee - A function applied to each item in the
2493
 * array to produce the next step in the reduction.
2494
 * The `iteratee` should complete with the next state of the reduction.
2495
 * If the iteratee complete with an error, the reduction is stopped and the
2496
 * main `callback` is immediately called with the error.
2497
 * Invoked with (memo, item, callback).
2498
 * @param {Function} [callback] - A callback which is called after all the
2499
 * `iteratee` functions have finished. Result is the reduced value. Invoked with
2500
 * (err, result).
2501
 * @example
2502
 *
2503
 * async.reduce([1,2,3], 0, function(memo, item, callback) {
2504
 *     // pointless async:
2505
 *     process.nextTick(function() {
2506
 *         callback(null, memo + item)
2507
 *     });
2508
 * }, function(err, result) {
2509
 *     // result is now equal to the last value of memo, which is 6
2510
 * });
2511
 */
2512
function reduce(coll, memo, iteratee, callback) {
2513
    callback = once(callback || noop);
2514
    var _iteratee = wrapAsync(iteratee);
2515
    eachOfSeries(coll, function(x, i, callback) {
2516
        _iteratee(memo, x, function(err, v) {
2517
            memo = v;
2518
            callback(err);
2519
        });
2520
    }, function(err) {
2521
        callback(err, memo);
2522
    });
2523
}
2524

    
2525
/**
2526
 * Version of the compose function that is more natural to read. Each function
2527
 * consumes the return value of the previous function. It is the equivalent of
2528
 * [compose]{@link module:ControlFlow.compose} with the arguments reversed.
2529
 *
2530
 * Each function is executed with the `this` binding of the composed function.
2531
 *
2532
 * @name seq
2533
 * @static
2534
 * @memberOf module:ControlFlow
2535
 * @method
2536
 * @see [async.compose]{@link module:ControlFlow.compose}
2537
 * @category Control Flow
2538
 * @param {...AsyncFunction} functions - the asynchronous functions to compose
2539
 * @returns {Function} a function that composes the `functions` in order
2540
 * @example
2541
 *
2542
 * // Requires lodash (or underscore), express3 and dresende's orm2.
2543
 * // Part of an app, that fetches cats of the logged user.
2544
 * // This example uses `seq` function to avoid overnesting and error
2545
 * // handling clutter.
2546
 * app.get('/cats', function(request, response) {
2547
 *     var User = request.models.User;
2548
 *     async.seq(
2549
 *         _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
2550
 *         function(user, fn) {
2551
 *             user.getCats(fn);      // 'getCats' has signature (callback(err, data))
2552
 *         }
2553
 *     )(req.session.user_id, function (err, cats) {
2554
 *         if (err) {
2555
 *             console.error(err);
2556
 *             response.json({ status: 'error', message: err.message });
2557
 *         } else {
2558
 *             response.json({ status: 'ok', message: 'Cats found', data: cats });
2559
 *         }
2560
 *     });
2561
 * });
2562
 */
2563
function seq(/*...functions*/) {
2564
    var _functions = arrayMap(arguments, wrapAsync);
2565
    return function(/*...args*/) {
2566
        var args = slice(arguments);
2567
        var that = this;
2568

    
2569
        var cb = args[args.length - 1];
2570
        if (typeof cb == 'function') {
2571
            args.pop();
2572
        } else {
2573
            cb = noop;
2574
        }
2575

    
2576
        reduce(_functions, args, function(newargs, fn, cb) {
2577
            fn.apply(that, newargs.concat(function(err/*, ...nextargs*/) {
2578
                var nextargs = slice(arguments, 1);
2579
                cb(err, nextargs);
2580
            }));
2581
        },
2582
        function(err, results) {
2583
            cb.apply(that, [err].concat(results));
2584
        });
2585
    };
2586
}
2587

    
2588
/**
2589
 * Creates a function which is a composition of the passed asynchronous
2590
 * functions. Each function consumes the return value of the function that
2591
 * follows. Composing functions `f()`, `g()`, and `h()` would produce the result
2592
 * of `f(g(h()))`, only this version uses callbacks to obtain the return values.
2593
 *
2594
 * Each function is executed with the `this` binding of the composed function.
2595
 *
2596
 * @name compose
2597
 * @static
2598
 * @memberOf module:ControlFlow
2599
 * @method
2600
 * @category Control Flow
2601
 * @param {...AsyncFunction} functions - the asynchronous functions to compose
2602
 * @returns {Function} an asynchronous function that is the composed
2603
 * asynchronous `functions`
2604
 * @example
2605
 *
2606
 * function add1(n, callback) {
2607
 *     setTimeout(function () {
2608
 *         callback(null, n + 1);
2609
 *     }, 10);
2610
 * }
2611
 *
2612
 * function mul3(n, callback) {
2613
 *     setTimeout(function () {
2614
 *         callback(null, n * 3);
2615
 *     }, 10);
2616
 * }
2617
 *
2618
 * var add1mul3 = async.compose(mul3, add1);
2619
 * add1mul3(4, function (err, result) {
2620
 *     // result now equals 15
2621
 * });
2622
 */
2623
var compose = function(/*...args*/) {
2624
    return seq.apply(null, slice(arguments).reverse());
2625
};
2626

    
2627
var _concat = Array.prototype.concat;
2628

    
2629
/**
2630
 * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time.
2631
 *
2632
 * @name concatLimit
2633
 * @static
2634
 * @memberOf module:Collections
2635
 * @method
2636
 * @see [async.concat]{@link module:Collections.concat}
2637
 * @category Collection
2638
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2639
 * @param {number} limit - The maximum number of async operations at a time.
2640
 * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
2641
 * which should use an array as its result. Invoked with (item, callback).
2642
 * @param {Function} [callback] - A callback which is called after all the
2643
 * `iteratee` functions have finished, or an error occurs. Results is an array
2644
 * containing the concatenated results of the `iteratee` function. Invoked with
2645
 * (err, results).
2646
 */
2647
var concatLimit = function(coll, limit, iteratee, callback) {
2648
    callback = callback || noop;
2649
    var _iteratee = wrapAsync(iteratee);
2650
    mapLimit(coll, limit, function(val, callback) {
2651
        _iteratee(val, function(err /*, ...args*/) {
2652
            if (err) return callback(err);
2653
            return callback(null, slice(arguments, 1));
2654
        });
2655
    }, function(err, mapResults) {
2656
        var result = [];
2657
        for (var i = 0; i < mapResults.length; i++) {
2658
            if (mapResults[i]) {
2659
                result = _concat.apply(result, mapResults[i]);
2660
            }
2661
        }
2662

    
2663
        return callback(err, result);
2664
    });
2665
};
2666

    
2667
/**
2668
 * Applies `iteratee` to each item in `coll`, concatenating the results. Returns
2669
 * the concatenated list. The `iteratee`s are called in parallel, and the
2670
 * results are concatenated as they return. There is no guarantee that the
2671
 * results array will be returned in the original order of `coll` passed to the
2672
 * `iteratee` function.
2673
 *
2674
 * @name concat
2675
 * @static
2676
 * @memberOf module:Collections
2677
 * @method
2678
 * @category Collection
2679
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2680
 * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
2681
 * which should use an array as its result. Invoked with (item, callback).
2682
 * @param {Function} [callback(err)] - A callback which is called after all the
2683
 * `iteratee` functions have finished, or an error occurs. Results is an array
2684
 * containing the concatenated results of the `iteratee` function. Invoked with
2685
 * (err, results).
2686
 * @example
2687
 *
2688
 * async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files) {
2689
 *     // files is now a list of filenames that exist in the 3 directories
2690
 * });
2691
 */
2692
var concat = doLimit(concatLimit, Infinity);
2693

    
2694
/**
2695
 * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time.
2696
 *
2697
 * @name concatSeries
2698
 * @static
2699
 * @memberOf module:Collections
2700
 * @method
2701
 * @see [async.concat]{@link module:Collections.concat}
2702
 * @category Collection
2703
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2704
 * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`.
2705
 * The iteratee should complete with an array an array of results.
2706
 * Invoked with (item, callback).
2707
 * @param {Function} [callback(err)] - A callback which is called after all the
2708
 * `iteratee` functions have finished, or an error occurs. Results is an array
2709
 * containing the concatenated results of the `iteratee` function. Invoked with
2710
 * (err, results).
2711
 */
2712
var concatSeries = doLimit(concatLimit, 1);
2713

    
2714
/**
2715
 * Returns a function that when called, calls-back with the values provided.
2716
 * Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to
2717
 * [`auto`]{@link module:ControlFlow.auto}.
2718
 *
2719
 * @name constant
2720
 * @static
2721
 * @memberOf module:Utils
2722
 * @method
2723
 * @category Util
2724
 * @param {...*} arguments... - Any number of arguments to automatically invoke
2725
 * callback with.
2726
 * @returns {AsyncFunction} Returns a function that when invoked, automatically
2727
 * invokes the callback with the previous given arguments.
2728
 * @example
2729
 *
2730
 * async.waterfall([
2731
 *     async.constant(42),
2732
 *     function (value, next) {
2733
 *         // value === 42
2734
 *     },
2735
 *     //...
2736
 * ], callback);
2737
 *
2738
 * async.waterfall([
2739
 *     async.constant(filename, "utf8"),
2740
 *     fs.readFile,
2741
 *     function (fileData, next) {
2742
 *         //...
2743
 *     }
2744
 *     //...
2745
 * ], callback);
2746
 *
2747
 * async.auto({
2748
 *     hostname: async.constant("https://server.net/"),
2749
 *     port: findFreePort,
2750
 *     launchServer: ["hostname", "port", function (options, cb) {
2751
 *         startServer(options, cb);
2752
 *     }],
2753
 *     //...
2754
 * }, callback);
2755
 */
2756
var constant = function(/*...values*/) {
2757
    var values = slice(arguments);
2758
    var args = [null].concat(values);
2759
    return function (/*...ignoredArgs, callback*/) {
2760
        var callback = arguments[arguments.length - 1];
2761
        return callback.apply(this, args);
2762
    };
2763
};
2764

    
2765
/**
2766
 * This method returns the first argument it receives.
2767
 *
2768
 * @static
2769
 * @since 0.1.0
2770
 * @memberOf _
2771
 * @category Util
2772
 * @param {*} value Any value.
2773
 * @returns {*} Returns `value`.
2774
 * @example
2775
 *
2776
 * var object = { 'a': 1 };
2777
 *
2778
 * console.log(_.identity(object) === object);
2779
 * // => true
2780
 */
2781
function identity(value) {
2782
  return value;
2783
}
2784

    
2785
function _createTester(check, getResult) {
2786
    return function(eachfn, arr, iteratee, cb) {
2787
        cb = cb || noop;
2788
        var testPassed = false;
2789
        var testResult;
2790
        eachfn(arr, function(value, _, callback) {
2791
            iteratee(value, function(err, result) {
2792
                if (err) {
2793
                    callback(err);
2794
                } else if (check(result) && !testResult) {
2795
                    testPassed = true;
2796
                    testResult = getResult(true, value);
2797
                    callback(null, breakLoop);
2798
                } else {
2799
                    callback();
2800
                }
2801
            });
2802
        }, function(err) {
2803
            if (err) {
2804
                cb(err);
2805
            } else {
2806
                cb(null, testPassed ? testResult : getResult(false));
2807
            }
2808
        });
2809
    };
2810
}
2811

    
2812
function _findGetResult(v, x) {
2813
    return x;
2814
}
2815

    
2816
/**
2817
 * Returns the first value in `coll` that passes an async truth test. The
2818
 * `iteratee` is applied in parallel, meaning the first iteratee to return
2819
 * `true` will fire the detect `callback` with that result. That means the
2820
 * result might not be the first item in the original `coll` (in terms of order)
2821
 * that passes the test.
2822

    
2823
 * If order within the original `coll` is important, then look at
2824
 * [`detectSeries`]{@link module:Collections.detectSeries}.
2825
 *
2826
 * @name detect
2827
 * @static
2828
 * @memberOf module:Collections
2829
 * @method
2830
 * @alias find
2831
 * @category Collections
2832
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2833
 * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
2834
 * The iteratee must complete with a boolean value as its result.
2835
 * Invoked with (item, callback).
2836
 * @param {Function} [callback] - A callback which is called as soon as any
2837
 * iteratee returns `true`, or after all the `iteratee` functions have finished.
2838
 * Result will be the first item in the array that passes the truth test
2839
 * (iteratee) or the value `undefined` if none passed. Invoked with
2840
 * (err, result).
2841
 * @example
2842
 *
2843
 * async.detect(['file1','file2','file3'], function(filePath, callback) {
2844
 *     fs.access(filePath, function(err) {
2845
 *         callback(null, !err)
2846
 *     });
2847
 * }, function(err, result) {
2848
 *     // result now equals the first file in the list that exists
2849
 * });
2850
 */
2851
var detect = doParallel(_createTester(identity, _findGetResult));
2852

    
2853
/**
2854
 * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a
2855
 * time.
2856
 *
2857
 * @name detectLimit
2858
 * @static
2859
 * @memberOf module:Collections
2860
 * @method
2861
 * @see [async.detect]{@link module:Collections.detect}
2862
 * @alias findLimit
2863
 * @category Collections
2864
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2865
 * @param {number} limit - The maximum number of async operations at a time.
2866
 * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
2867
 * The iteratee must complete with a boolean value as its result.
2868
 * Invoked with (item, callback).
2869
 * @param {Function} [callback] - A callback which is called as soon as any
2870
 * iteratee returns `true`, or after all the `iteratee` functions have finished.
2871
 * Result will be the first item in the array that passes the truth test
2872
 * (iteratee) or the value `undefined` if none passed. Invoked with
2873
 * (err, result).
2874
 */
2875
var detectLimit = doParallelLimit(_createTester(identity, _findGetResult));
2876

    
2877
/**
2878
 * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time.
2879
 *
2880
 * @name detectSeries
2881
 * @static
2882
 * @memberOf module:Collections
2883
 * @method
2884
 * @see [async.detect]{@link module:Collections.detect}
2885
 * @alias findSeries
2886
 * @category Collections
2887
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
2888
 * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
2889
 * The iteratee must complete with a boolean value as its result.
2890
 * Invoked with (item, callback).
2891
 * @param {Function} [callback] - A callback which is called as soon as any
2892
 * iteratee returns `true`, or after all the `iteratee` functions have finished.
2893
 * Result will be the first item in the array that passes the truth test
2894
 * (iteratee) or the value `undefined` if none passed. Invoked with
2895
 * (err, result).
2896
 */
2897
var detectSeries = doLimit(detectLimit, 1);
2898

    
2899
function consoleFunc(name) {
2900
    return function (fn/*, ...args*/) {
2901
        var args = slice(arguments, 1);
2902
        args.push(function (err/*, ...args*/) {
2903
            var args = slice(arguments, 1);
2904
            if (typeof console === 'object') {
2905
                if (err) {
2906
                    if (console.error) {
2907
                        console.error(err);
2908
                    }
2909
                } else if (console[name]) {
2910
                    arrayEach(args, function (x) {
2911
                        console[name](x);
2912
                    });
2913
                }
2914
            }
2915
        });
2916
        wrapAsync(fn).apply(null, args);
2917
    };
2918
}
2919

    
2920
/**
2921
 * Logs the result of an [`async` function]{@link AsyncFunction} to the
2922
 * `console` using `console.dir` to display the properties of the resulting object.
2923
 * Only works in Node.js or in browsers that support `console.dir` and
2924
 * `console.error` (such as FF and Chrome).
2925
 * If multiple arguments are returned from the async function,
2926
 * `console.dir` is called on each argument in order.
2927
 *
2928
 * @name dir
2929
 * @static
2930
 * @memberOf module:Utils
2931
 * @method
2932
 * @category Util
2933
 * @param {AsyncFunction} function - The function you want to eventually apply
2934
 * all arguments to.
2935
 * @param {...*} arguments... - Any number of arguments to apply to the function.
2936
 * @example
2937
 *
2938
 * // in a module
2939
 * var hello = function(name, callback) {
2940
 *     setTimeout(function() {
2941
 *         callback(null, {hello: name});
2942
 *     }, 1000);
2943
 * };
2944
 *
2945
 * // in the node repl
2946
 * node> async.dir(hello, 'world');
2947
 * {hello: 'world'}
2948
 */
2949
var dir = consoleFunc('dir');
2950

    
2951
/**
2952
 * The post-check version of [`during`]{@link module:ControlFlow.during}. To reflect the difference in
2953
 * the order of operations, the arguments `test` and `fn` are switched.
2954
 *
2955
 * Also a version of [`doWhilst`]{@link module:ControlFlow.doWhilst} with asynchronous `test` function.
2956
 * @name doDuring
2957
 * @static
2958
 * @memberOf module:ControlFlow
2959
 * @method
2960
 * @see [async.during]{@link module:ControlFlow.during}
2961
 * @category Control Flow
2962
 * @param {AsyncFunction} fn - An async function which is called each time
2963
 * `test` passes. Invoked with (callback).
2964
 * @param {AsyncFunction} test - asynchronous truth test to perform before each
2965
 * execution of `fn`. Invoked with (...args, callback), where `...args` are the
2966
 * non-error args from the previous callback of `fn`.
2967
 * @param {Function} [callback] - A callback which is called after the test
2968
 * function has failed and repeated execution of `fn` has stopped. `callback`
2969
 * will be passed an error if one occurred, otherwise `null`.
2970
 */
2971
function doDuring(fn, test, callback) {
2972
    callback = onlyOnce(callback || noop);
2973
    var _fn = wrapAsync(fn);
2974
    var _test = wrapAsync(test);
2975

    
2976
    function next(err/*, ...args*/) {
2977
        if (err) return callback(err);
2978
        var args = slice(arguments, 1);
2979
        args.push(check);
2980
        _test.apply(this, args);
2981
    }
2982

    
2983
    function check(err, truth) {
2984
        if (err) return callback(err);
2985
        if (!truth) return callback(null);
2986
        _fn(next);
2987
    }
2988

    
2989
    check(null, true);
2990

    
2991
}
2992

    
2993
/**
2994
 * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in
2995
 * the order of operations, the arguments `test` and `iteratee` are switched.
2996
 *
2997
 * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
2998
 *
2999
 * @name doWhilst
3000
 * @static
3001
 * @memberOf module:ControlFlow
3002
 * @method
3003
 * @see [async.whilst]{@link module:ControlFlow.whilst}
3004
 * @category Control Flow
3005
 * @param {AsyncFunction} iteratee - A function which is called each time `test`
3006
 * passes. Invoked with (callback).
3007
 * @param {Function} test - synchronous truth test to perform after each
3008
 * execution of `iteratee`. Invoked with any non-error callback results of
3009
 * `iteratee`.
3010
 * @param {Function} [callback] - A callback which is called after the test
3011
 * function has failed and repeated execution of `iteratee` has stopped.
3012
 * `callback` will be passed an error and any arguments passed to the final
3013
 * `iteratee`'s callback. Invoked with (err, [results]);
3014
 */
3015
function doWhilst(iteratee, test, callback) {
3016
    callback = onlyOnce(callback || noop);
3017
    var _iteratee = wrapAsync(iteratee);
3018
    var next = function(err/*, ...args*/) {
3019
        if (err) return callback(err);
3020
        var args = slice(arguments, 1);
3021
        if (test.apply(this, args)) return _iteratee(next);
3022
        callback.apply(null, [null].concat(args));
3023
    };
3024
    _iteratee(next);
3025
}
3026

    
3027
/**
3028
 * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the
3029
 * argument ordering differs from `until`.
3030
 *
3031
 * @name doUntil
3032
 * @static
3033
 * @memberOf module:ControlFlow
3034
 * @method
3035
 * @see [async.doWhilst]{@link module:ControlFlow.doWhilst}
3036
 * @category Control Flow
3037
 * @param {AsyncFunction} iteratee - An async function which is called each time
3038
 * `test` fails. Invoked with (callback).
3039
 * @param {Function} test - synchronous truth test to perform after each
3040
 * execution of `iteratee`. Invoked with any non-error callback results of
3041
 * `iteratee`.
3042
 * @param {Function} [callback] - A callback which is called after the test
3043
 * function has passed and repeated execution of `iteratee` has stopped. `callback`
3044
 * will be passed an error and any arguments passed to the final `iteratee`'s
3045
 * callback. Invoked with (err, [results]);
3046
 */
3047
function doUntil(iteratee, test, callback) {
3048
    doWhilst(iteratee, function() {
3049
        return !test.apply(this, arguments);
3050
    }, callback);
3051
}
3052

    
3053
/**
3054
 * Like [`whilst`]{@link module:ControlFlow.whilst}, except the `test` is an asynchronous function that
3055
 * is passed a callback in the form of `function (err, truth)`. If error is
3056
 * passed to `test` or `fn`, the main callback is immediately called with the
3057
 * value of the error.
3058
 *
3059
 * @name during
3060
 * @static
3061
 * @memberOf module:ControlFlow
3062
 * @method
3063
 * @see [async.whilst]{@link module:ControlFlow.whilst}
3064
 * @category Control Flow
3065
 * @param {AsyncFunction} test - asynchronous truth test to perform before each
3066
 * execution of `fn`. Invoked with (callback).
3067
 * @param {AsyncFunction} fn - An async function which is called each time
3068
 * `test` passes. Invoked with (callback).
3069
 * @param {Function} [callback] - A callback which is called after the test
3070
 * function has failed and repeated execution of `fn` has stopped. `callback`
3071
 * will be passed an error, if one occurred, otherwise `null`.
3072
 * @example
3073
 *
3074
 * var count = 0;
3075
 *
3076
 * async.during(
3077
 *     function (callback) {
3078
 *         return callback(null, count < 5);
3079
 *     },
3080
 *     function (callback) {
3081
 *         count++;
3082
 *         setTimeout(callback, 1000);
3083
 *     },
3084
 *     function (err) {
3085
 *         // 5 seconds have passed
3086
 *     }
3087
 * );
3088
 */
3089
function during(test, fn, callback) {
3090
    callback = onlyOnce(callback || noop);
3091
    var _fn = wrapAsync(fn);
3092
    var _test = wrapAsync(test);
3093

    
3094
    function next(err) {
3095
        if (err) return callback(err);
3096
        _test(check);
3097
    }
3098

    
3099
    function check(err, truth) {
3100
        if (err) return callback(err);
3101
        if (!truth) return callback(null);
3102
        _fn(next);
3103
    }
3104

    
3105
    _test(check);
3106
}
3107

    
3108
function _withoutIndex(iteratee) {
3109
    return function (value, index, callback) {
3110
        return iteratee(value, callback);
3111
    };
3112
}
3113

    
3114
/**
3115
 * Applies the function `iteratee` to each item in `coll`, in parallel.
3116
 * The `iteratee` is called with an item from the list, and a callback for when
3117
 * it has finished. If the `iteratee` passes an error to its `callback`, the
3118
 * main `callback` (for the `each` function) is immediately called with the
3119
 * error.
3120
 *
3121
 * Note, that since this function applies `iteratee` to each item in parallel,
3122
 * there is no guarantee that the iteratee functions will complete in order.
3123
 *
3124
 * @name each
3125
 * @static
3126
 * @memberOf module:Collections
3127
 * @method
3128
 * @alias forEach
3129
 * @category Collection
3130
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3131
 * @param {AsyncFunction} iteratee - An async function to apply to
3132
 * each item in `coll`. Invoked with (item, callback).
3133
 * The array index is not passed to the iteratee.
3134
 * If you need the index, use `eachOf`.
3135
 * @param {Function} [callback] - A callback which is called when all
3136
 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
3137
 * @example
3138
 *
3139
 * // assuming openFiles is an array of file names and saveFile is a function
3140
 * // to save the modified contents of that file:
3141
 *
3142
 * async.each(openFiles, saveFile, function(err){
3143
 *   // if any of the saves produced an error, err would equal that error
3144
 * });
3145
 *
3146
 * // assuming openFiles is an array of file names
3147
 * async.each(openFiles, function(file, callback) {
3148
 *
3149
 *     // Perform operation on file here.
3150
 *     console.log('Processing file ' + file);
3151
 *
3152
 *     if( file.length > 32 ) {
3153
 *       console.log('This file name is too long');
3154
 *       callback('File name too long');
3155
 *     } else {
3156
 *       // Do work to process file here
3157
 *       console.log('File processed');
3158
 *       callback();
3159
 *     }
3160
 * }, function(err) {
3161
 *     // if any of the file processing produced an error, err would equal that error
3162
 *     if( err ) {
3163
 *       // One of the iterations produced an error.
3164
 *       // All processing will now stop.
3165
 *       console.log('A file failed to process');
3166
 *     } else {
3167
 *       console.log('All files have been processed successfully');
3168
 *     }
3169
 * });
3170
 */
3171
function eachLimit(coll, iteratee, callback) {
3172
    eachOf(coll, _withoutIndex(wrapAsync(iteratee)), callback);
3173
}
3174

    
3175
/**
3176
 * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time.
3177
 *
3178
 * @name eachLimit
3179
 * @static
3180
 * @memberOf module:Collections
3181
 * @method
3182
 * @see [async.each]{@link module:Collections.each}
3183
 * @alias forEachLimit
3184
 * @category Collection
3185
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3186
 * @param {number} limit - The maximum number of async operations at a time.
3187
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
3188
 * `coll`.
3189
 * The array index is not passed to the iteratee.
3190
 * If you need the index, use `eachOfLimit`.
3191
 * Invoked with (item, callback).
3192
 * @param {Function} [callback] - A callback which is called when all
3193
 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
3194
 */
3195
function eachLimit$1(coll, limit, iteratee, callback) {
3196
    _eachOfLimit(limit)(coll, _withoutIndex(wrapAsync(iteratee)), callback);
3197
}
3198

    
3199
/**
3200
 * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time.
3201
 *
3202
 * @name eachSeries
3203
 * @static
3204
 * @memberOf module:Collections
3205
 * @method
3206
 * @see [async.each]{@link module:Collections.each}
3207
 * @alias forEachSeries
3208
 * @category Collection
3209
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3210
 * @param {AsyncFunction} iteratee - An async function to apply to each
3211
 * item in `coll`.
3212
 * The array index is not passed to the iteratee.
3213
 * If you need the index, use `eachOfSeries`.
3214
 * Invoked with (item, callback).
3215
 * @param {Function} [callback] - A callback which is called when all
3216
 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
3217
 */
3218
var eachSeries = doLimit(eachLimit$1, 1);
3219

    
3220
/**
3221
 * Wrap an async function and ensure it calls its callback on a later tick of
3222
 * the event loop.  If the function already calls its callback on a next tick,
3223
 * no extra deferral is added. This is useful for preventing stack overflows
3224
 * (`RangeError: Maximum call stack size exceeded`) and generally keeping
3225
 * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony)
3226
 * contained. ES2017 `async` functions are returned as-is -- they are immune
3227
 * to Zalgo's corrupting influences, as they always resolve on a later tick.
3228
 *
3229
 * @name ensureAsync
3230
 * @static
3231
 * @memberOf module:Utils
3232
 * @method
3233
 * @category Util
3234
 * @param {AsyncFunction} fn - an async function, one that expects a node-style
3235
 * callback as its last argument.
3236
 * @returns {AsyncFunction} Returns a wrapped function with the exact same call
3237
 * signature as the function passed in.
3238
 * @example
3239
 *
3240
 * function sometimesAsync(arg, callback) {
3241
 *     if (cache[arg]) {
3242
 *         return callback(null, cache[arg]); // this would be synchronous!!
3243
 *     } else {
3244
 *         doSomeIO(arg, callback); // this IO would be asynchronous
3245
 *     }
3246
 * }
3247
 *
3248
 * // this has a risk of stack overflows if many results are cached in a row
3249
 * async.mapSeries(args, sometimesAsync, done);
3250
 *
3251
 * // this will defer sometimesAsync's callback if necessary,
3252
 * // preventing stack overflows
3253
 * async.mapSeries(args, async.ensureAsync(sometimesAsync), done);
3254
 */
3255
function ensureAsync(fn) {
3256
    if (isAsync(fn)) return fn;
3257
    return initialParams(function (args, callback) {
3258
        var sync = true;
3259
        args.push(function () {
3260
            var innerArgs = arguments;
3261
            if (sync) {
3262
                setImmediate$1(function () {
3263
                    callback.apply(null, innerArgs);
3264
                });
3265
            } else {
3266
                callback.apply(null, innerArgs);
3267
            }
3268
        });
3269
        fn.apply(this, args);
3270
        sync = false;
3271
    });
3272
}
3273

    
3274
function notId(v) {
3275
    return !v;
3276
}
3277

    
3278
/**
3279
 * Returns `true` if every element in `coll` satisfies an async test. If any
3280
 * iteratee call returns `false`, the main `callback` is immediately called.
3281
 *
3282
 * @name every
3283
 * @static
3284
 * @memberOf module:Collections
3285
 * @method
3286
 * @alias all
3287
 * @category Collection
3288
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3289
 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
3290
 * in the collection in parallel.
3291
 * The iteratee must complete with a boolean result value.
3292
 * Invoked with (item, callback).
3293
 * @param {Function} [callback] - A callback which is called after all the
3294
 * `iteratee` functions have finished. Result will be either `true` or `false`
3295
 * depending on the values of the async tests. Invoked with (err, result).
3296
 * @example
3297
 *
3298
 * async.every(['file1','file2','file3'], function(filePath, callback) {
3299
 *     fs.access(filePath, function(err) {
3300
 *         callback(null, !err)
3301
 *     });
3302
 * }, function(err, result) {
3303
 *     // if result is true then every file exists
3304
 * });
3305
 */
3306
var every = doParallel(_createTester(notId, notId));
3307

    
3308
/**
3309
 * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time.
3310
 *
3311
 * @name everyLimit
3312
 * @static
3313
 * @memberOf module:Collections
3314
 * @method
3315
 * @see [async.every]{@link module:Collections.every}
3316
 * @alias allLimit
3317
 * @category Collection
3318
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3319
 * @param {number} limit - The maximum number of async operations at a time.
3320
 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
3321
 * in the collection in parallel.
3322
 * The iteratee must complete with a boolean result value.
3323
 * Invoked with (item, callback).
3324
 * @param {Function} [callback] - A callback which is called after all the
3325
 * `iteratee` functions have finished. Result will be either `true` or `false`
3326
 * depending on the values of the async tests. Invoked with (err, result).
3327
 */
3328
var everyLimit = doParallelLimit(_createTester(notId, notId));
3329

    
3330
/**
3331
 * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time.
3332
 *
3333
 * @name everySeries
3334
 * @static
3335
 * @memberOf module:Collections
3336
 * @method
3337
 * @see [async.every]{@link module:Collections.every}
3338
 * @alias allSeries
3339
 * @category Collection
3340
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3341
 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
3342
 * in the collection in series.
3343
 * The iteratee must complete with a boolean result value.
3344
 * Invoked with (item, callback).
3345
 * @param {Function} [callback] - A callback which is called after all the
3346
 * `iteratee` functions have finished. Result will be either `true` or `false`
3347
 * depending on the values of the async tests. Invoked with (err, result).
3348
 */
3349
var everySeries = doLimit(everyLimit, 1);
3350

    
3351
/**
3352
 * The base implementation of `_.property` without support for deep paths.
3353
 *
3354
 * @private
3355
 * @param {string} key The key of the property to get.
3356
 * @returns {Function} Returns the new accessor function.
3357
 */
3358
function baseProperty(key) {
3359
  return function(object) {
3360
    return object == null ? undefined : object[key];
3361
  };
3362
}
3363

    
3364
function filterArray(eachfn, arr, iteratee, callback) {
3365
    var truthValues = new Array(arr.length);
3366
    eachfn(arr, function (x, index, callback) {
3367
        iteratee(x, function (err, v) {
3368
            truthValues[index] = !!v;
3369
            callback(err);
3370
        });
3371
    }, function (err) {
3372
        if (err) return callback(err);
3373
        var results = [];
3374
        for (var i = 0; i < arr.length; i++) {
3375
            if (truthValues[i]) results.push(arr[i]);
3376
        }
3377
        callback(null, results);
3378
    });
3379
}
3380

    
3381
function filterGeneric(eachfn, coll, iteratee, callback) {
3382
    var results = [];
3383
    eachfn(coll, function (x, index, callback) {
3384
        iteratee(x, function (err, v) {
3385
            if (err) {
3386
                callback(err);
3387
            } else {
3388
                if (v) {
3389
                    results.push({index: index, value: x});
3390
                }
3391
                callback();
3392
            }
3393
        });
3394
    }, function (err) {
3395
        if (err) {
3396
            callback(err);
3397
        } else {
3398
            callback(null, arrayMap(results.sort(function (a, b) {
3399
                return a.index - b.index;
3400
            }), baseProperty('value')));
3401
        }
3402
    });
3403
}
3404

    
3405
function _filter(eachfn, coll, iteratee, callback) {
3406
    var filter = isArrayLike(coll) ? filterArray : filterGeneric;
3407
    filter(eachfn, coll, wrapAsync(iteratee), callback || noop);
3408
}
3409

    
3410
/**
3411
 * Returns a new array of all the values in `coll` which pass an async truth
3412
 * test. This operation is performed in parallel, but the results array will be
3413
 * in the same order as the original.
3414
 *
3415
 * @name filter
3416
 * @static
3417
 * @memberOf module:Collections
3418
 * @method
3419
 * @alias select
3420
 * @category Collection
3421
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3422
 * @param {Function} iteratee - A truth test to apply to each item in `coll`.
3423
 * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
3424
 * with a boolean argument once it has completed. Invoked with (item, callback).
3425
 * @param {Function} [callback] - A callback which is called after all the
3426
 * `iteratee` functions have finished. Invoked with (err, results).
3427
 * @example
3428
 *
3429
 * async.filter(['file1','file2','file3'], function(filePath, callback) {
3430
 *     fs.access(filePath, function(err) {
3431
 *         callback(null, !err)
3432
 *     });
3433
 * }, function(err, results) {
3434
 *     // results now equals an array of the existing files
3435
 * });
3436
 */
3437
var filter = doParallel(_filter);
3438

    
3439
/**
3440
 * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a
3441
 * time.
3442
 *
3443
 * @name filterLimit
3444
 * @static
3445
 * @memberOf module:Collections
3446
 * @method
3447
 * @see [async.filter]{@link module:Collections.filter}
3448
 * @alias selectLimit
3449
 * @category Collection
3450
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3451
 * @param {number} limit - The maximum number of async operations at a time.
3452
 * @param {Function} iteratee - A truth test to apply to each item in `coll`.
3453
 * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
3454
 * with a boolean argument once it has completed. Invoked with (item, callback).
3455
 * @param {Function} [callback] - A callback which is called after all the
3456
 * `iteratee` functions have finished. Invoked with (err, results).
3457
 */
3458
var filterLimit = doParallelLimit(_filter);
3459

    
3460
/**
3461
 * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time.
3462
 *
3463
 * @name filterSeries
3464
 * @static
3465
 * @memberOf module:Collections
3466
 * @method
3467
 * @see [async.filter]{@link module:Collections.filter}
3468
 * @alias selectSeries
3469
 * @category Collection
3470
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3471
 * @param {Function} iteratee - A truth test to apply to each item in `coll`.
3472
 * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
3473
 * with a boolean argument once it has completed. Invoked with (item, callback).
3474
 * @param {Function} [callback] - A callback which is called after all the
3475
 * `iteratee` functions have finished. Invoked with (err, results)
3476
 */
3477
var filterSeries = doLimit(filterLimit, 1);
3478

    
3479
/**
3480
 * Calls the asynchronous function `fn` with a callback parameter that allows it
3481
 * to call itself again, in series, indefinitely.
3482

    
3483
 * If an error is passed to the callback then `errback` is called with the
3484
 * error, and execution stops, otherwise it will never be called.
3485
 *
3486
 * @name forever
3487
 * @static
3488
 * @memberOf module:ControlFlow
3489
 * @method
3490
 * @category Control Flow
3491
 * @param {AsyncFunction} fn - an async function to call repeatedly.
3492
 * Invoked with (next).
3493
 * @param {Function} [errback] - when `fn` passes an error to it's callback,
3494
 * this function will be called, and execution stops. Invoked with (err).
3495
 * @example
3496
 *
3497
 * async.forever(
3498
 *     function(next) {
3499
 *         // next is suitable for passing to things that need a callback(err [, whatever]);
3500
 *         // it will result in this function being called again.
3501
 *     },
3502
 *     function(err) {
3503
 *         // if next is called with a value in its first parameter, it will appear
3504
 *         // in here as 'err', and execution will stop.
3505
 *     }
3506
 * );
3507
 */
3508
function forever(fn, errback) {
3509
    var done = onlyOnce(errback || noop);
3510
    var task = wrapAsync(ensureAsync(fn));
3511

    
3512
    function next(err) {
3513
        if (err) return done(err);
3514
        task(next);
3515
    }
3516
    next();
3517
}
3518

    
3519
/**
3520
 * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time.
3521
 *
3522
 * @name groupByLimit
3523
 * @static
3524
 * @memberOf module:Collections
3525
 * @method
3526
 * @see [async.groupBy]{@link module:Collections.groupBy}
3527
 * @category Collection
3528
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3529
 * @param {number} limit - The maximum number of async operations at a time.
3530
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
3531
 * `coll`.
3532
 * The iteratee should complete with a `key` to group the value under.
3533
 * Invoked with (value, callback).
3534
 * @param {Function} [callback] - A callback which is called when all `iteratee`
3535
 * functions have finished, or an error occurs. Result is an `Object` whoses
3536
 * properties are arrays of values which returned the corresponding key.
3537
 */
3538
var groupByLimit = function(coll, limit, iteratee, callback) {
3539
    callback = callback || noop;
3540
    var _iteratee = wrapAsync(iteratee);
3541
    mapLimit(coll, limit, function(val, callback) {
3542
        _iteratee(val, function(err, key) {
3543
            if (err) return callback(err);
3544
            return callback(null, {key: key, val: val});
3545
        });
3546
    }, function(err, mapResults) {
3547
        var result = {};
3548
        // from MDN, handle object having an `hasOwnProperty` prop
3549
        var hasOwnProperty = Object.prototype.hasOwnProperty;
3550

    
3551
        for (var i = 0; i < mapResults.length; i++) {
3552
            if (mapResults[i]) {
3553
                var key = mapResults[i].key;
3554
                var val = mapResults[i].val;
3555

    
3556
                if (hasOwnProperty.call(result, key)) {
3557
                    result[key].push(val);
3558
                } else {
3559
                    result[key] = [val];
3560
                }
3561
            }
3562
        }
3563

    
3564
        return callback(err, result);
3565
    });
3566
};
3567

    
3568
/**
3569
 * Returns a new object, where each value corresponds to an array of items, from
3570
 * `coll`, that returned the corresponding key. That is, the keys of the object
3571
 * correspond to the values passed to the `iteratee` callback.
3572
 *
3573
 * Note: Since this function applies the `iteratee` to each item in parallel,
3574
 * there is no guarantee that the `iteratee` functions will complete in order.
3575
 * However, the values for each key in the `result` will be in the same order as
3576
 * the original `coll`. For Objects, the values will roughly be in the order of
3577
 * the original Objects' keys (but this can vary across JavaScript engines).
3578
 *
3579
 * @name groupBy
3580
 * @static
3581
 * @memberOf module:Collections
3582
 * @method
3583
 * @category Collection
3584
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3585
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
3586
 * `coll`.
3587
 * The iteratee should complete with a `key` to group the value under.
3588
 * Invoked with (value, callback).
3589
 * @param {Function} [callback] - A callback which is called when all `iteratee`
3590
 * functions have finished, or an error occurs. Result is an `Object` whoses
3591
 * properties are arrays of values which returned the corresponding key.
3592
 * @example
3593
 *
3594
 * async.groupBy(['userId1', 'userId2', 'userId3'], function(userId, callback) {
3595
 *     db.findById(userId, function(err, user) {
3596
 *         if (err) return callback(err);
3597
 *         return callback(null, user.age);
3598
 *     });
3599
 * }, function(err, result) {
3600
 *     // result is object containing the userIds grouped by age
3601
 *     // e.g. { 30: ['userId1', 'userId3'], 42: ['userId2']};
3602
 * });
3603
 */
3604
var groupBy = doLimit(groupByLimit, Infinity);
3605

    
3606
/**
3607
 * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time.
3608
 *
3609
 * @name groupBySeries
3610
 * @static
3611
 * @memberOf module:Collections
3612
 * @method
3613
 * @see [async.groupBy]{@link module:Collections.groupBy}
3614
 * @category Collection
3615
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
3616
 * @param {number} limit - The maximum number of async operations at a time.
3617
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
3618
 * `coll`.
3619
 * The iteratee should complete with a `key` to group the value under.
3620
 * Invoked with (value, callback).
3621
 * @param {Function} [callback] - A callback which is called when all `iteratee`
3622
 * functions have finished, or an error occurs. Result is an `Object` whoses
3623
 * properties are arrays of values which returned the corresponding key.
3624
 */
3625
var groupBySeries = doLimit(groupByLimit, 1);
3626

    
3627
/**
3628
 * Logs the result of an `async` function to the `console`. Only works in
3629
 * Node.js or in browsers that support `console.log` and `console.error` (such
3630
 * as FF and Chrome). If multiple arguments are returned from the async
3631
 * function, `console.log` is called on each argument in order.
3632
 *
3633
 * @name log
3634
 * @static
3635
 * @memberOf module:Utils
3636
 * @method
3637
 * @category Util
3638
 * @param {AsyncFunction} function - The function you want to eventually apply
3639
 * all arguments to.
3640
 * @param {...*} arguments... - Any number of arguments to apply to the function.
3641
 * @example
3642
 *
3643
 * // in a module
3644
 * var hello = function(name, callback) {
3645
 *     setTimeout(function() {
3646
 *         callback(null, 'hello ' + name);
3647
 *     }, 1000);
3648
 * };
3649
 *
3650
 * // in the node repl
3651
 * node> async.log(hello, 'world');
3652
 * 'hello world'
3653
 */
3654
var log = consoleFunc('log');
3655

    
3656
/**
3657
 * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a
3658
 * time.
3659
 *
3660
 * @name mapValuesLimit
3661
 * @static
3662
 * @memberOf module:Collections
3663
 * @method
3664
 * @see [async.mapValues]{@link module:Collections.mapValues}
3665
 * @category Collection
3666
 * @param {Object} obj - A collection to iterate over.
3667
 * @param {number} limit - The maximum number of async operations at a time.
3668
 * @param {AsyncFunction} iteratee - A function to apply to each value and key
3669
 * in `coll`.
3670
 * The iteratee should complete with the transformed value as its result.
3671
 * Invoked with (value, key, callback).
3672
 * @param {Function} [callback] - A callback which is called when all `iteratee`
3673
 * functions have finished, or an error occurs. `result` is a new object consisting
3674
 * of each key from `obj`, with each transformed value on the right-hand side.
3675
 * Invoked with (err, result).
3676
 */
3677
function mapValuesLimit(obj, limit, iteratee, callback) {
3678
    callback = once(callback || noop);
3679
    var newObj = {};
3680
    var _iteratee = wrapAsync(iteratee);
3681
    eachOfLimit(obj, limit, function(val, key, next) {
3682
        _iteratee(val, key, function (err, result) {
3683
            if (err) return next(err);
3684
            newObj[key] = result;
3685
            next();
3686
        });
3687
    }, function (err) {
3688
        callback(err, newObj);
3689
    });
3690
}
3691

    
3692
/**
3693
 * A relative of [`map`]{@link module:Collections.map}, designed for use with objects.
3694
 *
3695
 * Produces a new Object by mapping each value of `obj` through the `iteratee`
3696
 * function. The `iteratee` is called each `value` and `key` from `obj` and a
3697
 * callback for when it has finished processing. Each of these callbacks takes
3698
 * two arguments: an `error`, and the transformed item from `obj`. If `iteratee`
3699
 * passes an error to its callback, the main `callback` (for the `mapValues`
3700
 * function) is immediately called with the error.
3701
 *
3702
 * Note, the order of the keys in the result is not guaranteed.  The keys will
3703
 * be roughly in the order they complete, (but this is very engine-specific)
3704
 *
3705
 * @name mapValues
3706
 * @static
3707
 * @memberOf module:Collections
3708
 * @method
3709
 * @category Collection
3710
 * @param {Object} obj - A collection to iterate over.
3711
 * @param {AsyncFunction} iteratee - A function to apply to each value and key
3712
 * in `coll`.
3713
 * The iteratee should complete with the transformed value as its result.
3714
 * Invoked with (value, key, callback).
3715
 * @param {Function} [callback] - A callback which is called when all `iteratee`
3716
 * functions have finished, or an error occurs. `result` is a new object consisting
3717
 * of each key from `obj`, with each transformed value on the right-hand side.
3718
 * Invoked with (err, result).
3719
 * @example
3720
 *
3721
 * async.mapValues({
3722
 *     f1: 'file1',
3723
 *     f2: 'file2',
3724
 *     f3: 'file3'
3725
 * }, function (file, key, callback) {
3726
 *   fs.stat(file, callback);
3727
 * }, function(err, result) {
3728
 *     // result is now a map of stats for each file, e.g.
3729
 *     // {
3730
 *     //     f1: [stats for file1],
3731
 *     //     f2: [stats for file2],
3732
 *     //     f3: [stats for file3]
3733
 *     // }
3734
 * });
3735
 */
3736

    
3737
var mapValues = doLimit(mapValuesLimit, Infinity);
3738

    
3739
/**
3740
 * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time.
3741
 *
3742
 * @name mapValuesSeries
3743
 * @static
3744
 * @memberOf module:Collections
3745
 * @method
3746
 * @see [async.mapValues]{@link module:Collections.mapValues}
3747
 * @category Collection
3748
 * @param {Object} obj - A collection to iterate over.
3749
 * @param {AsyncFunction} iteratee - A function to apply to each value and key
3750
 * in `coll`.
3751
 * The iteratee should complete with the transformed value as its result.
3752
 * Invoked with (value, key, callback).
3753
 * @param {Function} [callback] - A callback which is called when all `iteratee`
3754
 * functions have finished, or an error occurs. `result` is a new object consisting
3755
 * of each key from `obj`, with each transformed value on the right-hand side.
3756
 * Invoked with (err, result).
3757
 */
3758
var mapValuesSeries = doLimit(mapValuesLimit, 1);
3759

    
3760
function has(obj, key) {
3761
    return key in obj;
3762
}
3763

    
3764
/**
3765
 * Caches the results of an async function. When creating a hash to store
3766
 * function results against, the callback is omitted from the hash and an
3767
 * optional hash function can be used.
3768
 *
3769
 * If no hash function is specified, the first argument is used as a hash key,
3770
 * which may work reasonably if it is a string or a data type that converts to a
3771
 * distinct string. Note that objects and arrays will not behave reasonably.
3772
 * Neither will cases where the other arguments are significant. In such cases,
3773
 * specify your own hash function.
3774
 *
3775
 * The cache of results is exposed as the `memo` property of the function
3776
 * returned by `memoize`.
3777
 *
3778
 * @name memoize
3779
 * @static
3780
 * @memberOf module:Utils
3781
 * @method
3782
 * @category Util
3783
 * @param {AsyncFunction} fn - The async function to proxy and cache results from.
3784
 * @param {Function} hasher - An optional function for generating a custom hash
3785
 * for storing results. It has all the arguments applied to it apart from the
3786
 * callback, and must be synchronous.
3787
 * @returns {AsyncFunction} a memoized version of `fn`
3788
 * @example
3789
 *
3790
 * var slow_fn = function(name, callback) {
3791
 *     // do something
3792
 *     callback(null, result);
3793
 * };
3794
 * var fn = async.memoize(slow_fn);
3795
 *
3796
 * // fn can now be used as if it were slow_fn
3797
 * fn('some name', function() {
3798
 *     // callback
3799
 * });
3800
 */
3801
function memoize(fn, hasher) {
3802
    var memo = Object.create(null);
3803
    var queues = Object.create(null);
3804
    hasher = hasher || identity;
3805
    var _fn = wrapAsync(fn);
3806
    var memoized = initialParams(function memoized(args, callback) {
3807
        var key = hasher.apply(null, args);
3808
        if (has(memo, key)) {
3809
            setImmediate$1(function() {
3810
                callback.apply(null, memo[key]);
3811
            });
3812
        } else if (has(queues, key)) {
3813
            queues[key].push(callback);
3814
        } else {
3815
            queues[key] = [callback];
3816
            _fn.apply(null, args.concat(function(/*args*/) {
3817
                var args = slice(arguments);
3818
                memo[key] = args;
3819
                var q = queues[key];
3820
                delete queues[key];
3821
                for (var i = 0, l = q.length; i < l; i++) {
3822
                    q[i].apply(null, args);
3823
                }
3824
            }));
3825
        }
3826
    });
3827
    memoized.memo = memo;
3828
    memoized.unmemoized = fn;
3829
    return memoized;
3830
}
3831

    
3832
/**
3833
 * Calls `callback` on a later loop around the event loop. In Node.js this just
3834
 * calls `process.nextTick`.  In the browser it will use `setImmediate` if
3835
 * available, otherwise `setTimeout(callback, 0)`, which means other higher
3836
 * priority events may precede the execution of `callback`.
3837
 *
3838
 * This is used internally for browser-compatibility purposes.
3839
 *
3840
 * @name nextTick
3841
 * @static
3842
 * @memberOf module:Utils
3843
 * @method
3844
 * @see [async.setImmediate]{@link module:Utils.setImmediate}
3845
 * @category Util
3846
 * @param {Function} callback - The function to call on a later loop around
3847
 * the event loop. Invoked with (args...).
3848
 * @param {...*} args... - any number of additional arguments to pass to the
3849
 * callback on the next tick.
3850
 * @example
3851
 *
3852
 * var call_order = [];
3853
 * async.nextTick(function() {
3854
 *     call_order.push('two');
3855
 *     // call_order now equals ['one','two']
3856
 * });
3857
 * call_order.push('one');
3858
 *
3859
 * async.setImmediate(function (a, b, c) {
3860
 *     // a, b, and c equal 1, 2, and 3
3861
 * }, 1, 2, 3);
3862
 */
3863
var _defer$1;
3864

    
3865
if (hasNextTick) {
3866
    _defer$1 = process.nextTick;
3867
} else if (hasSetImmediate) {
3868
    _defer$1 = setImmediate;
3869
} else {
3870
    _defer$1 = fallback;
3871
}
3872

    
3873
var nextTick = wrap(_defer$1);
3874

    
3875
function _parallel(eachfn, tasks, callback) {
3876
    callback = callback || noop;
3877
    var results = isArrayLike(tasks) ? [] : {};
3878

    
3879
    eachfn(tasks, function (task, key, callback) {
3880
        wrapAsync(task)(function (err, result) {
3881
            if (arguments.length > 2) {
3882
                result = slice(arguments, 1);
3883
            }
3884
            results[key] = result;
3885
            callback(err);
3886
        });
3887
    }, function (err) {
3888
        callback(err, results);
3889
    });
3890
}
3891

    
3892
/**
3893
 * Run the `tasks` collection of functions in parallel, without waiting until
3894
 * the previous function has completed. If any of the functions pass an error to
3895
 * its callback, the main `callback` is immediately called with the value of the
3896
 * error. Once the `tasks` have completed, the results are passed to the final
3897
 * `callback` as an array.
3898
 *
3899
 * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about
3900
 * parallel execution of code.  If your tasks do not use any timers or perform
3901
 * any I/O, they will actually be executed in series.  Any synchronous setup
3902
 * sections for each task will happen one after the other.  JavaScript remains
3903
 * single-threaded.
3904
 *
3905
 * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the
3906
 * execution of other tasks when a task fails.
3907
 *
3908
 * It is also possible to use an object instead of an array. Each property will
3909
 * be run as a function and the results will be passed to the final `callback`
3910
 * as an object instead of an array. This can be a more readable way of handling
3911
 * results from {@link async.parallel}.
3912
 *
3913
 * @name parallel
3914
 * @static
3915
 * @memberOf module:ControlFlow
3916
 * @method
3917
 * @category Control Flow
3918
 * @param {Array|Iterable|Object} tasks - A collection of
3919
 * [async functions]{@link AsyncFunction} to run.
3920
 * Each async function can complete with any number of optional `result` values.
3921
 * @param {Function} [callback] - An optional callback to run once all the
3922
 * functions have completed successfully. This function gets a results array
3923
 * (or object) containing all the result arguments passed to the task callbacks.
3924
 * Invoked with (err, results).
3925
 *
3926
 * @example
3927
 * async.parallel([
3928
 *     function(callback) {
3929
 *         setTimeout(function() {
3930
 *             callback(null, 'one');
3931
 *         }, 200);
3932
 *     },
3933
 *     function(callback) {
3934
 *         setTimeout(function() {
3935
 *             callback(null, 'two');
3936
 *         }, 100);
3937
 *     }
3938
 * ],
3939
 * // optional callback
3940
 * function(err, results) {
3941
 *     // the results array will equal ['one','two'] even though
3942
 *     // the second function had a shorter timeout.
3943
 * });
3944
 *
3945
 * // an example using an object instead of an array
3946
 * async.parallel({
3947
 *     one: function(callback) {
3948
 *         setTimeout(function() {
3949
 *             callback(null, 1);
3950
 *         }, 200);
3951
 *     },
3952
 *     two: function(callback) {
3953
 *         setTimeout(function() {
3954
 *             callback(null, 2);
3955
 *         }, 100);
3956
 *     }
3957
 * }, function(err, results) {
3958
 *     // results is now equals to: {one: 1, two: 2}
3959
 * });
3960
 */
3961
function parallelLimit(tasks, callback) {
3962
    _parallel(eachOf, tasks, callback);
3963
}
3964

    
3965
/**
3966
 * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a
3967
 * time.
3968
 *
3969
 * @name parallelLimit
3970
 * @static
3971
 * @memberOf module:ControlFlow
3972
 * @method
3973
 * @see [async.parallel]{@link module:ControlFlow.parallel}
3974
 * @category Control Flow
3975
 * @param {Array|Iterable|Object} tasks - A collection of
3976
 * [async functions]{@link AsyncFunction} to run.
3977
 * Each async function can complete with any number of optional `result` values.
3978
 * @param {number} limit - The maximum number of async operations at a time.
3979
 * @param {Function} [callback] - An optional callback to run once all the
3980
 * functions have completed successfully. This function gets a results array
3981
 * (or object) containing all the result arguments passed to the task callbacks.
3982
 * Invoked with (err, results).
3983
 */
3984
function parallelLimit$1(tasks, limit, callback) {
3985
    _parallel(_eachOfLimit(limit), tasks, callback);
3986
}
3987

    
3988
/**
3989
 * A queue of tasks for the worker function to complete.
3990
 * @typedef {Object} QueueObject
3991
 * @memberOf module:ControlFlow
3992
 * @property {Function} length - a function returning the number of items
3993
 * waiting to be processed. Invoke with `queue.length()`.
3994
 * @property {boolean} started - a boolean indicating whether or not any
3995
 * items have been pushed and processed by the queue.
3996
 * @property {Function} running - a function returning the number of items
3997
 * currently being processed. Invoke with `queue.running()`.
3998
 * @property {Function} workersList - a function returning the array of items
3999
 * currently being processed. Invoke with `queue.workersList()`.
4000
 * @property {Function} idle - a function returning false if there are items
4001
 * waiting or being processed, or true if not. Invoke with `queue.idle()`.
4002
 * @property {number} concurrency - an integer for determining how many `worker`
4003
 * functions should be run in parallel. This property can be changed after a
4004
 * `queue` is created to alter the concurrency on-the-fly.
4005
 * @property {Function} push - add a new task to the `queue`. Calls `callback`
4006
 * once the `worker` has finished processing the task. Instead of a single task,
4007
 * a `tasks` array can be submitted. The respective callback is used for every
4008
 * task in the list. Invoke with `queue.push(task, [callback])`,
4009
 * @property {Function} unshift - add a new task to the front of the `queue`.
4010
 * Invoke with `queue.unshift(task, [callback])`.
4011
 * @property {Function} remove - remove items from the queue that match a test
4012
 * function.  The test function will be passed an object with a `data` property,
4013
 * and a `priority` property, if this is a
4014
 * [priorityQueue]{@link module:ControlFlow.priorityQueue} object.
4015
 * Invoked with `queue.remove(testFn)`, where `testFn` is of the form
4016
 * `function ({data, priority}) {}` and returns a Boolean.
4017
 * @property {Function} saturated - a callback that is called when the number of
4018
 * running workers hits the `concurrency` limit, and further tasks will be
4019
 * queued.
4020
 * @property {Function} unsaturated - a callback that is called when the number
4021
 * of running workers is less than the `concurrency` & `buffer` limits, and
4022
 * further tasks will not be queued.
4023
 * @property {number} buffer - A minimum threshold buffer in order to say that
4024
 * the `queue` is `unsaturated`.
4025
 * @property {Function} empty - a callback that is called when the last item
4026
 * from the `queue` is given to a `worker`.
4027
 * @property {Function} drain - a callback that is called when the last item
4028
 * from the `queue` has returned from the `worker`.
4029
 * @property {Function} error - a callback that is called when a task errors.
4030
 * Has the signature `function(error, task)`.
4031
 * @property {boolean} paused - a boolean for determining whether the queue is
4032
 * in a paused state.
4033
 * @property {Function} pause - a function that pauses the processing of tasks
4034
 * until `resume()` is called. Invoke with `queue.pause()`.
4035
 * @property {Function} resume - a function that resumes the processing of
4036
 * queued tasks when the queue is paused. Invoke with `queue.resume()`.
4037
 * @property {Function} kill - a function that removes the `drain` callback and
4038
 * empties remaining tasks from the queue forcing it to go idle. No more tasks
4039
 * should be pushed to the queue after calling this function. Invoke with `queue.kill()`.
4040
 */
4041

    
4042
/**
4043
 * Creates a `queue` object with the specified `concurrency`. Tasks added to the
4044
 * `queue` are processed in parallel (up to the `concurrency` limit). If all
4045
 * `worker`s are in progress, the task is queued until one becomes available.
4046
 * Once a `worker` completes a `task`, that `task`'s callback is called.
4047
 *
4048
 * @name queue
4049
 * @static
4050
 * @memberOf module:ControlFlow
4051
 * @method
4052
 * @category Control Flow
4053
 * @param {AsyncFunction} worker - An async function for processing a queued task.
4054
 * If you want to handle errors from an individual task, pass a callback to
4055
 * `q.push()`. Invoked with (task, callback).
4056
 * @param {number} [concurrency=1] - An `integer` for determining how many
4057
 * `worker` functions should be run in parallel.  If omitted, the concurrency
4058
 * defaults to `1`.  If the concurrency is `0`, an error is thrown.
4059
 * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can
4060
 * attached as certain properties to listen for specific events during the
4061
 * lifecycle of the queue.
4062
 * @example
4063
 *
4064
 * // create a queue object with concurrency 2
4065
 * var q = async.queue(function(task, callback) {
4066
 *     console.log('hello ' + task.name);
4067
 *     callback();
4068
 * }, 2);
4069
 *
4070
 * // assign a callback
4071
 * q.drain = function() {
4072
 *     console.log('all items have been processed');
4073
 * };
4074
 *
4075
 * // add some items to the queue
4076
 * q.push({name: 'foo'}, function(err) {
4077
 *     console.log('finished processing foo');
4078
 * });
4079
 * q.push({name: 'bar'}, function (err) {
4080
 *     console.log('finished processing bar');
4081
 * });
4082
 *
4083
 * // add some items to the queue (batch-wise)
4084
 * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
4085
 *     console.log('finished processing item');
4086
 * });
4087
 *
4088
 * // add some items to the front of the queue
4089
 * q.unshift({name: 'bar'}, function (err) {
4090
 *     console.log('finished processing bar');
4091
 * });
4092
 */
4093
var queue$1 = function (worker, concurrency) {
4094
    var _worker = wrapAsync(worker);
4095
    return queue(function (items, cb) {
4096
        _worker(items[0], cb);
4097
    }, concurrency, 1);
4098
};
4099

    
4100
/**
4101
 * The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and
4102
 * completed in ascending priority order.
4103
 *
4104
 * @name priorityQueue
4105
 * @static
4106
 * @memberOf module:ControlFlow
4107
 * @method
4108
 * @see [async.queue]{@link module:ControlFlow.queue}
4109
 * @category Control Flow
4110
 * @param {AsyncFunction} worker - An async function for processing a queued task.
4111
 * If you want to handle errors from an individual task, pass a callback to
4112
 * `q.push()`.
4113
 * Invoked with (task, callback).
4114
 * @param {number} concurrency - An `integer` for determining how many `worker`
4115
 * functions should be run in parallel.  If omitted, the concurrency defaults to
4116
 * `1`.  If the concurrency is `0`, an error is thrown.
4117
 * @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are two
4118
 * differences between `queue` and `priorityQueue` objects:
4119
 * * `push(task, priority, [callback])` - `priority` should be a number. If an
4120
 *   array of `tasks` is given, all tasks will be assigned the same priority.
4121
 * * The `unshift` method was removed.
4122
 */
4123
var priorityQueue = function(worker, concurrency) {
4124
    // Start with a normal queue
4125
    var q = queue$1(worker, concurrency);
4126

    
4127
    // Override push to accept second parameter representing priority
4128
    q.push = function(data, priority, callback) {
4129
        if (callback == null) callback = noop;
4130
        if (typeof callback !== 'function') {
4131
            throw new Error('task callback must be a function');
4132
        }
4133
        q.started = true;
4134
        if (!isArray(data)) {
4135
            data = [data];
4136
        }
4137
        if (data.length === 0) {
4138
            // call drain immediately if there are no tasks
4139
            return setImmediate$1(function() {
4140
                q.drain();
4141
            });
4142
        }
4143

    
4144
        priority = priority || 0;
4145
        var nextNode = q._tasks.head;
4146
        while (nextNode && priority >= nextNode.priority) {
4147
            nextNode = nextNode.next;
4148
        }
4149

    
4150
        for (var i = 0, l = data.length; i < l; i++) {
4151
            var item = {
4152
                data: data[i],
4153
                priority: priority,
4154
                callback: callback
4155
            };
4156

    
4157
            if (nextNode) {
4158
                q._tasks.insertBefore(nextNode, item);
4159
            } else {
4160
                q._tasks.push(item);
4161
            }
4162
        }
4163
        setImmediate$1(q.process);
4164
    };
4165

    
4166
    // Remove unshift function
4167
    delete q.unshift;
4168

    
4169
    return q;
4170
};
4171

    
4172
/**
4173
 * Runs the `tasks` array of functions in parallel, without waiting until the
4174
 * previous function has completed. Once any of the `tasks` complete or pass an
4175
 * error to its callback, the main `callback` is immediately called. It's
4176
 * equivalent to `Promise.race()`.
4177
 *
4178
 * @name race
4179
 * @static
4180
 * @memberOf module:ControlFlow
4181
 * @method
4182
 * @category Control Flow
4183
 * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction}
4184
 * to run. Each function can complete with an optional `result` value.
4185
 * @param {Function} callback - A callback to run once any of the functions have
4186
 * completed. This function gets an error or result from the first function that
4187
 * completed. Invoked with (err, result).
4188
 * @returns undefined
4189
 * @example
4190
 *
4191
 * async.race([
4192
 *     function(callback) {
4193
 *         setTimeout(function() {
4194
 *             callback(null, 'one');
4195
 *         }, 200);
4196
 *     },
4197
 *     function(callback) {
4198
 *         setTimeout(function() {
4199
 *             callback(null, 'two');
4200
 *         }, 100);
4201
 *     }
4202
 * ],
4203
 * // main callback
4204
 * function(err, result) {
4205
 *     // the result will be equal to 'two' as it finishes earlier
4206
 * });
4207
 */
4208
function race(tasks, callback) {
4209
    callback = once(callback || noop);
4210
    if (!isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions'));
4211
    if (!tasks.length) return callback();
4212
    for (var i = 0, l = tasks.length; i < l; i++) {
4213
        wrapAsync(tasks[i])(callback);
4214
    }
4215
}
4216

    
4217
/**
4218
 * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order.
4219
 *
4220
 * @name reduceRight
4221
 * @static
4222
 * @memberOf module:Collections
4223
 * @method
4224
 * @see [async.reduce]{@link module:Collections.reduce}
4225
 * @alias foldr
4226
 * @category Collection
4227
 * @param {Array} array - A collection to iterate over.
4228
 * @param {*} memo - The initial state of the reduction.
4229
 * @param {AsyncFunction} iteratee - A function applied to each item in the
4230
 * array to produce the next step in the reduction.
4231
 * The `iteratee` should complete with the next state of the reduction.
4232
 * If the iteratee complete with an error, the reduction is stopped and the
4233
 * main `callback` is immediately called with the error.
4234
 * Invoked with (memo, item, callback).
4235
 * @param {Function} [callback] - A callback which is called after all the
4236
 * `iteratee` functions have finished. Result is the reduced value. Invoked with
4237
 * (err, result).
4238
 */
4239
function reduceRight (array, memo, iteratee, callback) {
4240
    var reversed = slice(array).reverse();
4241
    reduce(reversed, memo, iteratee, callback);
4242
}
4243

    
4244
/**
4245
 * Wraps the async function in another function that always completes with a
4246
 * result object, even when it errors.
4247
 *
4248
 * The result object has either the property `error` or `value`.
4249
 *
4250
 * @name reflect
4251
 * @static
4252
 * @memberOf module:Utils
4253
 * @method
4254
 * @category Util
4255
 * @param {AsyncFunction} fn - The async function you want to wrap
4256
 * @returns {Function} - A function that always passes null to it's callback as
4257
 * the error. The second argument to the callback will be an `object` with
4258
 * either an `error` or a `value` property.
4259
 * @example
4260
 *
4261
 * async.parallel([
4262
 *     async.reflect(function(callback) {
4263
 *         // do some stuff ...
4264
 *         callback(null, 'one');
4265
 *     }),
4266
 *     async.reflect(function(callback) {
4267
 *         // do some more stuff but error ...
4268
 *         callback('bad stuff happened');
4269
 *     }),
4270
 *     async.reflect(function(callback) {
4271
 *         // do some more stuff ...
4272
 *         callback(null, 'two');
4273
 *     })
4274
 * ],
4275
 * // optional callback
4276
 * function(err, results) {
4277
 *     // values
4278
 *     // results[0].value = 'one'
4279
 *     // results[1].error = 'bad stuff happened'
4280
 *     // results[2].value = 'two'
4281
 * });
4282
 */
4283
function reflect(fn) {
4284
    var _fn = wrapAsync(fn);
4285
    return initialParams(function reflectOn(args, reflectCallback) {
4286
        args.push(function callback(error, cbArg) {
4287
            if (error) {
4288
                reflectCallback(null, { error: error });
4289
            } else {
4290
                var value;
4291
                if (arguments.length <= 2) {
4292
                    value = cbArg;
4293
                } else {
4294
                    value = slice(arguments, 1);
4295
                }
4296
                reflectCallback(null, { value: value });
4297
            }
4298
        });
4299

    
4300
        return _fn.apply(this, args);
4301
    });
4302
}
4303

    
4304
/**
4305
 * A helper function that wraps an array or an object of functions with `reflect`.
4306
 *
4307
 * @name reflectAll
4308
 * @static
4309
 * @memberOf module:Utils
4310
 * @method
4311
 * @see [async.reflect]{@link module:Utils.reflect}
4312
 * @category Util
4313
 * @param {Array|Object|Iterable} tasks - The collection of
4314
 * [async functions]{@link AsyncFunction} to wrap in `async.reflect`.
4315
 * @returns {Array} Returns an array of async functions, each wrapped in
4316
 * `async.reflect`
4317
 * @example
4318
 *
4319
 * let tasks = [
4320
 *     function(callback) {
4321
 *         setTimeout(function() {
4322
 *             callback(null, 'one');
4323
 *         }, 200);
4324
 *     },
4325
 *     function(callback) {
4326
 *         // do some more stuff but error ...
4327
 *         callback(new Error('bad stuff happened'));
4328
 *     },
4329
 *     function(callback) {
4330
 *         setTimeout(function() {
4331
 *             callback(null, 'two');
4332
 *         }, 100);
4333
 *     }
4334
 * ];
4335
 *
4336
 * async.parallel(async.reflectAll(tasks),
4337
 * // optional callback
4338
 * function(err, results) {
4339
 *     // values
4340
 *     // results[0].value = 'one'
4341
 *     // results[1].error = Error('bad stuff happened')
4342
 *     // results[2].value = 'two'
4343
 * });
4344
 *
4345
 * // an example using an object instead of an array
4346
 * let tasks = {
4347
 *     one: function(callback) {
4348
 *         setTimeout(function() {
4349
 *             callback(null, 'one');
4350
 *         }, 200);
4351
 *     },
4352
 *     two: function(callback) {
4353
 *         callback('two');
4354
 *     },
4355
 *     three: function(callback) {
4356
 *         setTimeout(function() {
4357
 *             callback(null, 'three');
4358
 *         }, 100);
4359
 *     }
4360
 * };
4361
 *
4362
 * async.parallel(async.reflectAll(tasks),
4363
 * // optional callback
4364
 * function(err, results) {
4365
 *     // values
4366
 *     // results.one.value = 'one'
4367
 *     // results.two.error = 'two'
4368
 *     // results.three.value = 'three'
4369
 * });
4370
 */
4371
function reflectAll(tasks) {
4372
    var results;
4373
    if (isArray(tasks)) {
4374
        results = arrayMap(tasks, reflect);
4375
    } else {
4376
        results = {};
4377
        baseForOwn(tasks, function(task, key) {
4378
            results[key] = reflect.call(this, task);
4379
        });
4380
    }
4381
    return results;
4382
}
4383

    
4384
function reject$1(eachfn, arr, iteratee, callback) {
4385
    _filter(eachfn, arr, function(value, cb) {
4386
        iteratee(value, function(err, v) {
4387
            cb(err, !v);
4388
        });
4389
    }, callback);
4390
}
4391

    
4392
/**
4393
 * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test.
4394
 *
4395
 * @name reject
4396
 * @static
4397
 * @memberOf module:Collections
4398
 * @method
4399
 * @see [async.filter]{@link module:Collections.filter}
4400
 * @category Collection
4401
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
4402
 * @param {Function} iteratee - An async truth test to apply to each item in
4403
 * `coll`.
4404
 * The should complete with a boolean value as its `result`.
4405
 * Invoked with (item, callback).
4406
 * @param {Function} [callback] - A callback which is called after all the
4407
 * `iteratee` functions have finished. Invoked with (err, results).
4408
 * @example
4409
 *
4410
 * async.reject(['file1','file2','file3'], function(filePath, callback) {
4411
 *     fs.access(filePath, function(err) {
4412
 *         callback(null, !err)
4413
 *     });
4414
 * }, function(err, results) {
4415
 *     // results now equals an array of missing files
4416
 *     createFiles(results);
4417
 * });
4418
 */
4419
var reject = doParallel(reject$1);
4420

    
4421
/**
4422
 * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a
4423
 * time.
4424
 *
4425
 * @name rejectLimit
4426
 * @static
4427
 * @memberOf module:Collections
4428
 * @method
4429
 * @see [async.reject]{@link module:Collections.reject}
4430
 * @category Collection
4431
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
4432
 * @param {number} limit - The maximum number of async operations at a time.
4433
 * @param {Function} iteratee - An async truth test to apply to each item in
4434
 * `coll`.
4435
 * The should complete with a boolean value as its `result`.
4436
 * Invoked with (item, callback).
4437
 * @param {Function} [callback] - A callback which is called after all the
4438
 * `iteratee` functions have finished. Invoked with (err, results).
4439
 */
4440
var rejectLimit = doParallelLimit(reject$1);
4441

    
4442
/**
4443
 * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time.
4444
 *
4445
 * @name rejectSeries
4446
 * @static
4447
 * @memberOf module:Collections
4448
 * @method
4449
 * @see [async.reject]{@link module:Collections.reject}
4450
 * @category Collection
4451
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
4452
 * @param {Function} iteratee - An async truth test to apply to each item in
4453
 * `coll`.
4454
 * The should complete with a boolean value as its `result`.
4455
 * Invoked with (item, callback).
4456
 * @param {Function} [callback] - A callback which is called after all the
4457
 * `iteratee` functions have finished. Invoked with (err, results).
4458
 */
4459
var rejectSeries = doLimit(rejectLimit, 1);
4460

    
4461
/**
4462
 * Creates a function that returns `value`.
4463
 *
4464
 * @static
4465
 * @memberOf _
4466
 * @since 2.4.0
4467
 * @category Util
4468
 * @param {*} value The value to return from the new function.
4469
 * @returns {Function} Returns the new constant function.
4470
 * @example
4471
 *
4472
 * var objects = _.times(2, _.constant({ 'a': 1 }));
4473
 *
4474
 * console.log(objects);
4475
 * // => [{ 'a': 1 }, { 'a': 1 }]
4476
 *
4477
 * console.log(objects[0] === objects[1]);
4478
 * // => true
4479
 */
4480
function constant$1(value) {
4481
  return function() {
4482
    return value;
4483
  };
4484
}
4485

    
4486
/**
4487
 * Attempts to get a successful response from `task` no more than `times` times
4488
 * before returning an error. If the task is successful, the `callback` will be
4489
 * passed the result of the successful task. If all attempts fail, the callback
4490
 * will be passed the error and result (if any) of the final attempt.
4491
 *
4492
 * @name retry
4493
 * @static
4494
 * @memberOf module:ControlFlow
4495
 * @method
4496
 * @category Control Flow
4497
 * @see [async.retryable]{@link module:ControlFlow.retryable}
4498
 * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an
4499
 * object with `times` and `interval` or a number.
4500
 * * `times` - The number of attempts to make before giving up.  The default
4501
 *   is `5`.
4502
 * * `interval` - The time to wait between retries, in milliseconds.  The
4503
 *   default is `0`. The interval may also be specified as a function of the
4504
 *   retry count (see example).
4505
 * * `errorFilter` - An optional synchronous function that is invoked on
4506
 *   erroneous result. If it returns `true` the retry attempts will continue;
4507
 *   if the function returns `false` the retry flow is aborted with the current
4508
 *   attempt's error and result being returned to the final callback.
4509
 *   Invoked with (err).
4510
 * * If `opts` is a number, the number specifies the number of times to retry,
4511
 *   with the default interval of `0`.
4512
 * @param {AsyncFunction} task - An async function to retry.
4513
 * Invoked with (callback).
4514
 * @param {Function} [callback] - An optional callback which is called when the
4515
 * task has succeeded, or after the final failed attempt. It receives the `err`
4516
 * and `result` arguments of the last attempt at completing the `task`. Invoked
4517
 * with (err, results).
4518
 *
4519
 * @example
4520
 *
4521
 * // The `retry` function can be used as a stand-alone control flow by passing
4522
 * // a callback, as shown below:
4523
 *
4524
 * // try calling apiMethod 3 times
4525
 * async.retry(3, apiMethod, function(err, result) {
4526
 *     // do something with the result
4527
 * });
4528
 *
4529
 * // try calling apiMethod 3 times, waiting 200 ms between each retry
4530
 * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
4531
 *     // do something with the result
4532
 * });
4533
 *
4534
 * // try calling apiMethod 10 times with exponential backoff
4535
 * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds)
4536
 * async.retry({
4537
 *   times: 10,
4538
 *   interval: function(retryCount) {
4539
 *     return 50 * Math.pow(2, retryCount);
4540
 *   }
4541
 * }, apiMethod, function(err, result) {
4542
 *     // do something with the result
4543
 * });
4544
 *
4545
 * // try calling apiMethod the default 5 times no delay between each retry
4546
 * async.retry(apiMethod, function(err, result) {
4547
 *     // do something with the result
4548
 * });
4549
 *
4550
 * // try calling apiMethod only when error condition satisfies, all other
4551
 * // errors will abort the retry control flow and return to final callback
4552
 * async.retry({
4553
 *   errorFilter: function(err) {
4554
 *     return err.message === 'Temporary error'; // only retry on a specific error
4555
 *   }
4556
 * }, apiMethod, function(err, result) {
4557
 *     // do something with the result
4558
 * });
4559
 *
4560
 * // to retry individual methods that are not as reliable within other
4561
 * // control flow functions, use the `retryable` wrapper:
4562
 * async.auto({
4563
 *     users: api.getUsers.bind(api),
4564
 *     payments: async.retryable(3, api.getPayments.bind(api))
4565
 * }, function(err, results) {
4566
 *     // do something with the results
4567
 * });
4568
 *
4569
 */
4570
function retry(opts, task, callback) {
4571
    var DEFAULT_TIMES = 5;
4572
    var DEFAULT_INTERVAL = 0;
4573

    
4574
    var options = {
4575
        times: DEFAULT_TIMES,
4576
        intervalFunc: constant$1(DEFAULT_INTERVAL)
4577
    };
4578

    
4579
    function parseTimes(acc, t) {
4580
        if (typeof t === 'object') {
4581
            acc.times = +t.times || DEFAULT_TIMES;
4582

    
4583
            acc.intervalFunc = typeof t.interval === 'function' ?
4584
                t.interval :
4585
                constant$1(+t.interval || DEFAULT_INTERVAL);
4586

    
4587
            acc.errorFilter = t.errorFilter;
4588
        } else if (typeof t === 'number' || typeof t === 'string') {
4589
            acc.times = +t || DEFAULT_TIMES;
4590
        } else {
4591
            throw new Error("Invalid arguments for async.retry");
4592
        }
4593
    }
4594

    
4595
    if (arguments.length < 3 && typeof opts === 'function') {
4596
        callback = task || noop;
4597
        task = opts;
4598
    } else {
4599
        parseTimes(options, opts);
4600
        callback = callback || noop;
4601
    }
4602

    
4603
    if (typeof task !== 'function') {
4604
        throw new Error("Invalid arguments for async.retry");
4605
    }
4606

    
4607
    var _task = wrapAsync(task);
4608

    
4609
    var attempt = 1;
4610
    function retryAttempt() {
4611
        _task(function(err) {
4612
            if (err && attempt++ < options.times &&
4613
                (typeof options.errorFilter != 'function' ||
4614
                    options.errorFilter(err))) {
4615
                setTimeout(retryAttempt, options.intervalFunc(attempt));
4616
            } else {
4617
                callback.apply(null, arguments);
4618
            }
4619
        });
4620
    }
4621

    
4622
    retryAttempt();
4623
}
4624

    
4625
/**
4626
 * A close relative of [`retry`]{@link module:ControlFlow.retry}.  This method
4627
 * wraps a task and makes it retryable, rather than immediately calling it
4628
 * with retries.
4629
 *
4630
 * @name retryable
4631
 * @static
4632
 * @memberOf module:ControlFlow
4633
 * @method
4634
 * @see [async.retry]{@link module:ControlFlow.retry}
4635
 * @category Control Flow
4636
 * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional
4637
 * options, exactly the same as from `retry`
4638
 * @param {AsyncFunction} task - the asynchronous function to wrap.
4639
 * This function will be passed any arguments passed to the returned wrapper.
4640
 * Invoked with (...args, callback).
4641
 * @returns {AsyncFunction} The wrapped function, which when invoked, will
4642
 * retry on an error, based on the parameters specified in `opts`.
4643
 * This function will accept the same parameters as `task`.
4644
 * @example
4645
 *
4646
 * async.auto({
4647
 *     dep1: async.retryable(3, getFromFlakyService),
4648
 *     process: ["dep1", async.retryable(3, function (results, cb) {
4649
 *         maybeProcessData(results.dep1, cb);
4650
 *     })]
4651
 * }, callback);
4652
 */
4653
var retryable = function (opts, task) {
4654
    if (!task) {
4655
        task = opts;
4656
        opts = null;
4657
    }
4658
    var _task = wrapAsync(task);
4659
    return initialParams(function (args, callback) {
4660
        function taskFn(cb) {
4661
            _task.apply(null, args.concat(cb));
4662
        }
4663

    
4664
        if (opts) retry(opts, taskFn, callback);
4665
        else retry(taskFn, callback);
4666

    
4667
    });
4668
};
4669

    
4670
/**
4671
 * Run the functions in the `tasks` collection in series, each one running once
4672
 * the previous function has completed. If any functions in the series pass an
4673
 * error to its callback, no more functions are run, and `callback` is
4674
 * immediately called with the value of the error. Otherwise, `callback`
4675
 * receives an array of results when `tasks` have completed.
4676
 *
4677
 * It is also possible to use an object instead of an array. Each property will
4678
 * be run as a function, and the results will be passed to the final `callback`
4679
 * as an object instead of an array. This can be a more readable way of handling
4680
 *  results from {@link async.series}.
4681
 *
4682
 * **Note** that while many implementations preserve the order of object
4683
 * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6)
4684
 * explicitly states that
4685
 *
4686
 * > The mechanics and order of enumerating the properties is not specified.
4687
 *
4688
 * So if you rely on the order in which your series of functions are executed,
4689
 * and want this to work on all platforms, consider using an array.
4690
 *
4691
 * @name series
4692
 * @static
4693
 * @memberOf module:ControlFlow
4694
 * @method
4695
 * @category Control Flow
4696
 * @param {Array|Iterable|Object} tasks - A collection containing
4697
 * [async functions]{@link AsyncFunction} to run in series.
4698
 * Each function can complete with any number of optional `result` values.
4699
 * @param {Function} [callback] - An optional callback to run once all the
4700
 * functions have completed. This function gets a results array (or object)
4701
 * containing all the result arguments passed to the `task` callbacks. Invoked
4702
 * with (err, result).
4703
 * @example
4704
 * async.series([
4705
 *     function(callback) {
4706
 *         // do some stuff ...
4707
 *         callback(null, 'one');
4708
 *     },
4709
 *     function(callback) {
4710
 *         // do some more stuff ...
4711
 *         callback(null, 'two');
4712
 *     }
4713
 * ],
4714
 * // optional callback
4715
 * function(err, results) {
4716
 *     // results is now equal to ['one', 'two']
4717
 * });
4718
 *
4719
 * async.series({
4720
 *     one: function(callback) {
4721
 *         setTimeout(function() {
4722
 *             callback(null, 1);
4723
 *         }, 200);
4724
 *     },
4725
 *     two: function(callback){
4726
 *         setTimeout(function() {
4727
 *             callback(null, 2);
4728
 *         }, 100);
4729
 *     }
4730
 * }, function(err, results) {
4731
 *     // results is now equal to: {one: 1, two: 2}
4732
 * });
4733
 */
4734
function series(tasks, callback) {
4735
    _parallel(eachOfSeries, tasks, callback);
4736
}
4737

    
4738
/**
4739
 * Returns `true` if at least one element in the `coll` satisfies an async test.
4740
 * If any iteratee call returns `true`, the main `callback` is immediately
4741
 * called.
4742
 *
4743
 * @name some
4744
 * @static
4745
 * @memberOf module:Collections
4746
 * @method
4747
 * @alias any
4748
 * @category Collection
4749
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
4750
 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
4751
 * in the collections in parallel.
4752
 * The iteratee should complete with a boolean `result` value.
4753
 * Invoked with (item, callback).
4754
 * @param {Function} [callback] - A callback which is called as soon as any
4755
 * iteratee returns `true`, or after all the iteratee functions have finished.
4756
 * Result will be either `true` or `false` depending on the values of the async
4757
 * tests. Invoked with (err, result).
4758
 * @example
4759
 *
4760
 * async.some(['file1','file2','file3'], function(filePath, callback) {
4761
 *     fs.access(filePath, function(err) {
4762
 *         callback(null, !err)
4763
 *     });
4764
 * }, function(err, result) {
4765
 *     // if result is true then at least one of the files exists
4766
 * });
4767
 */
4768
var some = doParallel(_createTester(Boolean, identity));
4769

    
4770
/**
4771
 * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time.
4772
 *
4773
 * @name someLimit
4774
 * @static
4775
 * @memberOf module:Collections
4776
 * @method
4777
 * @see [async.some]{@link module:Collections.some}
4778
 * @alias anyLimit
4779
 * @category Collection
4780
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
4781
 * @param {number} limit - The maximum number of async operations at a time.
4782
 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
4783
 * in the collections in parallel.
4784
 * The iteratee should complete with a boolean `result` value.
4785
 * Invoked with (item, callback).
4786
 * @param {Function} [callback] - A callback which is called as soon as any
4787
 * iteratee returns `true`, or after all the iteratee functions have finished.
4788
 * Result will be either `true` or `false` depending on the values of the async
4789
 * tests. Invoked with (err, result).
4790
 */
4791
var someLimit = doParallelLimit(_createTester(Boolean, identity));
4792

    
4793
/**
4794
 * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time.
4795
 *
4796
 * @name someSeries
4797
 * @static
4798
 * @memberOf module:Collections
4799
 * @method
4800
 * @see [async.some]{@link module:Collections.some}
4801
 * @alias anySeries
4802
 * @category Collection
4803
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
4804
 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
4805
 * in the collections in series.
4806
 * The iteratee should complete with a boolean `result` value.
4807
 * Invoked with (item, callback).
4808
 * @param {Function} [callback] - A callback which is called as soon as any
4809
 * iteratee returns `true`, or after all the iteratee functions have finished.
4810
 * Result will be either `true` or `false` depending on the values of the async
4811
 * tests. Invoked with (err, result).
4812
 */
4813
var someSeries = doLimit(someLimit, 1);
4814

    
4815
/**
4816
 * Sorts a list by the results of running each `coll` value through an async
4817
 * `iteratee`.
4818
 *
4819
 * @name sortBy
4820
 * @static
4821
 * @memberOf module:Collections
4822
 * @method
4823
 * @category Collection
4824
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
4825
 * @param {AsyncFunction} iteratee - An async function to apply to each item in
4826
 * `coll`.
4827
 * The iteratee should complete with a value to use as the sort criteria as
4828
 * its `result`.
4829
 * Invoked with (item, callback).
4830
 * @param {Function} callback - A callback which is called after all the
4831
 * `iteratee` functions have finished, or an error occurs. Results is the items
4832
 * from the original `coll` sorted by the values returned by the `iteratee`
4833
 * calls. Invoked with (err, results).
4834
 * @example
4835
 *
4836
 * async.sortBy(['file1','file2','file3'], function(file, callback) {
4837
 *     fs.stat(file, function(err, stats) {
4838
 *         callback(err, stats.mtime);
4839
 *     });
4840
 * }, function(err, results) {
4841
 *     // results is now the original array of files sorted by
4842
 *     // modified date
4843
 * });
4844
 *
4845
 * // By modifying the callback parameter the
4846
 * // sorting order can be influenced:
4847
 *
4848
 * // ascending order
4849
 * async.sortBy([1,9,3,5], function(x, callback) {
4850
 *     callback(null, x);
4851
 * }, function(err,result) {
4852
 *     // result callback
4853
 * });
4854
 *
4855
 * // descending order
4856
 * async.sortBy([1,9,3,5], function(x, callback) {
4857
 *     callback(null, x*-1);    //<- x*-1 instead of x, turns the order around
4858
 * }, function(err,result) {
4859
 *     // result callback
4860
 * });
4861
 */
4862
function sortBy (coll, iteratee, callback) {
4863
    var _iteratee = wrapAsync(iteratee);
4864
    map(coll, function (x, callback) {
4865
        _iteratee(x, function (err, criteria) {
4866
            if (err) return callback(err);
4867
            callback(null, {value: x, criteria: criteria});
4868
        });
4869
    }, function (err, results) {
4870
        if (err) return callback(err);
4871
        callback(null, arrayMap(results.sort(comparator), baseProperty('value')));
4872
    });
4873

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

    
4880
/**
4881
 * Sets a time limit on an asynchronous function. If the function does not call
4882
 * its callback within the specified milliseconds, it will be called with a
4883
 * timeout error. The code property for the error object will be `'ETIMEDOUT'`.
4884
 *
4885
 * @name timeout
4886
 * @static
4887
 * @memberOf module:Utils
4888
 * @method
4889
 * @category Util
4890
 * @param {AsyncFunction} asyncFn - The async function to limit in time.
4891
 * @param {number} milliseconds - The specified time limit.
4892
 * @param {*} [info] - Any variable you want attached (`string`, `object`, etc)
4893
 * to timeout Error for more information..
4894
 * @returns {AsyncFunction} Returns a wrapped function that can be used with any
4895
 * of the control flow functions.
4896
 * Invoke this function with the same parameters as you would `asyncFunc`.
4897
 * @example
4898
 *
4899
 * function myFunction(foo, callback) {
4900
 *     doAsyncTask(foo, function(err, data) {
4901
 *         // handle errors
4902
 *         if (err) return callback(err);
4903
 *
4904
 *         // do some stuff ...
4905
 *
4906
 *         // return processed data
4907
 *         return callback(null, data);
4908
 *     });
4909
 * }
4910
 *
4911
 * var wrapped = async.timeout(myFunction, 1000);
4912
 *
4913
 * // call `wrapped` as you would `myFunction`
4914
 * wrapped({ bar: 'bar' }, function(err, data) {
4915
 *     // if `myFunction` takes < 1000 ms to execute, `err`
4916
 *     // and `data` will have their expected values
4917
 *
4918
 *     // else `err` will be an Error with the code 'ETIMEDOUT'
4919
 * });
4920
 */
4921
function timeout(asyncFn, milliseconds, info) {
4922
    var fn = wrapAsync(asyncFn);
4923

    
4924
    return initialParams(function (args, callback) {
4925
        var timedOut = false;
4926
        var timer;
4927

    
4928
        function timeoutCallback() {
4929
            var name = asyncFn.name || 'anonymous';
4930
            var error  = new Error('Callback function "' + name + '" timed out.');
4931
            error.code = 'ETIMEDOUT';
4932
            if (info) {
4933
                error.info = info;
4934
            }
4935
            timedOut = true;
4936
            callback(error);
4937
        }
4938

    
4939
        args.push(function () {
4940
            if (!timedOut) {
4941
                callback.apply(null, arguments);
4942
                clearTimeout(timer);
4943
            }
4944
        });
4945

    
4946
        // setup timer and call original function
4947
        timer = setTimeout(timeoutCallback, milliseconds);
4948
        fn.apply(null, args);
4949
    });
4950
}
4951

    
4952
/* Built-in method references for those with the same name as other `lodash` methods. */
4953
var nativeCeil = Math.ceil;
4954
var nativeMax = Math.max;
4955

    
4956
/**
4957
 * The base implementation of `_.range` and `_.rangeRight` which doesn't
4958
 * coerce arguments.
4959
 *
4960
 * @private
4961
 * @param {number} start The start of the range.
4962
 * @param {number} end The end of the range.
4963
 * @param {number} step The value to increment or decrement by.
4964
 * @param {boolean} [fromRight] Specify iterating from right to left.
4965
 * @returns {Array} Returns the range of numbers.
4966
 */
4967
function baseRange(start, end, step, fromRight) {
4968
  var index = -1,
4969
      length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
4970
      result = Array(length);
4971

    
4972
  while (length--) {
4973
    result[fromRight ? length : ++index] = start;
4974
    start += step;
4975
  }
4976
  return result;
4977
}
4978

    
4979
/**
4980
 * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a
4981
 * time.
4982
 *
4983
 * @name timesLimit
4984
 * @static
4985
 * @memberOf module:ControlFlow
4986
 * @method
4987
 * @see [async.times]{@link module:ControlFlow.times}
4988
 * @category Control Flow
4989
 * @param {number} count - The number of times to run the function.
4990
 * @param {number} limit - The maximum number of async operations at a time.
4991
 * @param {AsyncFunction} iteratee - The async function to call `n` times.
4992
 * Invoked with the iteration index and a callback: (n, next).
4993
 * @param {Function} callback - see [async.map]{@link module:Collections.map}.
4994
 */
4995
function timeLimit(count, limit, iteratee, callback) {
4996
    var _iteratee = wrapAsync(iteratee);
4997
    mapLimit(baseRange(0, count, 1), limit, _iteratee, callback);
4998
}
4999

    
5000
/**
5001
 * Calls the `iteratee` function `n` times, and accumulates results in the same
5002
 * manner you would use with [map]{@link module:Collections.map}.
5003
 *
5004
 * @name times
5005
 * @static
5006
 * @memberOf module:ControlFlow
5007
 * @method
5008
 * @see [async.map]{@link module:Collections.map}
5009
 * @category Control Flow
5010
 * @param {number} n - The number of times to run the function.
5011
 * @param {AsyncFunction} iteratee - The async function to call `n` times.
5012
 * Invoked with the iteration index and a callback: (n, next).
5013
 * @param {Function} callback - see {@link module:Collections.map}.
5014
 * @example
5015
 *
5016
 * // Pretend this is some complicated async factory
5017
 * var createUser = function(id, callback) {
5018
 *     callback(null, {
5019
 *         id: 'user' + id
5020
 *     });
5021
 * };
5022
 *
5023
 * // generate 5 users
5024
 * async.times(5, function(n, next) {
5025
 *     createUser(n, function(err, user) {
5026
 *         next(err, user);
5027
 *     });
5028
 * }, function(err, users) {
5029
 *     // we should now have 5 users
5030
 * });
5031
 */
5032
var times = doLimit(timeLimit, Infinity);
5033

    
5034
/**
5035
 * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time.
5036
 *
5037
 * @name timesSeries
5038
 * @static
5039
 * @memberOf module:ControlFlow
5040
 * @method
5041
 * @see [async.times]{@link module:ControlFlow.times}
5042
 * @category Control Flow
5043
 * @param {number} n - The number of times to run the function.
5044
 * @param {AsyncFunction} iteratee - The async function to call `n` times.
5045
 * Invoked with the iteration index and a callback: (n, next).
5046
 * @param {Function} callback - see {@link module:Collections.map}.
5047
 */
5048
var timesSeries = doLimit(timeLimit, 1);
5049

    
5050
/**
5051
 * A relative of `reduce`.  Takes an Object or Array, and iterates over each
5052
 * element in series, each step potentially mutating an `accumulator` value.
5053
 * The type of the accumulator defaults to the type of collection passed in.
5054
 *
5055
 * @name transform
5056
 * @static
5057
 * @memberOf module:Collections
5058
 * @method
5059
 * @category Collection
5060
 * @param {Array|Iterable|Object} coll - A collection to iterate over.
5061
 * @param {*} [accumulator] - The initial state of the transform.  If omitted,
5062
 * it will default to an empty Object or Array, depending on the type of `coll`
5063
 * @param {AsyncFunction} iteratee - A function applied to each item in the
5064
 * collection that potentially modifies the accumulator.
5065
 * Invoked with (accumulator, item, key, callback).
5066
 * @param {Function} [callback] - A callback which is called after all the
5067
 * `iteratee` functions have finished. Result is the transformed accumulator.
5068
 * Invoked with (err, result).
5069
 * @example
5070
 *
5071
 * async.transform([1,2,3], function(acc, item, index, callback) {
5072
 *     // pointless async:
5073
 *     process.nextTick(function() {
5074
 *         acc.push(item * 2)
5075
 *         callback(null)
5076
 *     });
5077
 * }, function(err, result) {
5078
 *     // result is now equal to [2, 4, 6]
5079
 * });
5080
 *
5081
 * @example
5082
 *
5083
 * async.transform({a: 1, b: 2, c: 3}, function (obj, val, key, callback) {
5084
 *     setImmediate(function () {
5085
 *         obj[key] = val * 2;
5086
 *         callback();
5087
 *     })
5088
 * }, function (err, result) {
5089
 *     // result is equal to {a: 2, b: 4, c: 6}
5090
 * })
5091
 */
5092
function transform (coll, accumulator, iteratee, callback) {
5093
    if (arguments.length <= 3) {
5094
        callback = iteratee;
5095
        iteratee = accumulator;
5096
        accumulator = isArray(coll) ? [] : {};
5097
    }
5098
    callback = once(callback || noop);
5099
    var _iteratee = wrapAsync(iteratee);
5100

    
5101
    eachOf(coll, function(v, k, cb) {
5102
        _iteratee(accumulator, v, k, cb);
5103
    }, function(err) {
5104
        callback(err, accumulator);
5105
    });
5106
}
5107

    
5108
/**
5109
 * It runs each task in series but stops whenever any of the functions were
5110
 * successful. If one of the tasks were successful, the `callback` will be
5111
 * passed the result of the successful task. If all tasks fail, the callback
5112
 * will be passed the error and result (if any) of the final attempt.
5113
 *
5114
 * @name tryEach
5115
 * @static
5116
 * @memberOf module:ControlFlow
5117
 * @method
5118
 * @category Control Flow
5119
 * @param {Array|Iterable|Object} tasks - A collection containing functions to
5120
 * run, each function is passed a `callback(err, result)` it must call on
5121
 * completion with an error `err` (which can be `null`) and an optional `result`
5122
 * value.
5123
 * @param {Function} [callback] - An optional callback which is called when one
5124
 * of the tasks has succeeded, or all have failed. It receives the `err` and
5125
 * `result` arguments of the last attempt at completing the `task`. Invoked with
5126
 * (err, results).
5127
 * @example
5128
 * async.tryEach([
5129
 *     function getDataFromFirstWebsite(callback) {
5130
 *         // Try getting the data from the first website
5131
 *         callback(err, data);
5132
 *     },
5133
 *     function getDataFromSecondWebsite(callback) {
5134
 *         // First website failed,
5135
 *         // Try getting the data from the backup website
5136
 *         callback(err, data);
5137
 *     }
5138
 * ],
5139
 * // optional callback
5140
 * function(err, results) {
5141
 *     Now do something with the data.
5142
 * });
5143
 *
5144
 */
5145
function tryEach(tasks, callback) {
5146
    var error = null;
5147
    var result;
5148
    callback = callback || noop;
5149
    eachSeries(tasks, function(task, callback) {
5150
        wrapAsync(task)(function (err, res/*, ...args*/) {
5151
            if (arguments.length > 2) {
5152
                result = slice(arguments, 1);
5153
            } else {
5154
                result = res;
5155
            }
5156
            error = err;
5157
            callback(!err);
5158
        });
5159
    }, function () {
5160
        callback(error, result);
5161
    });
5162
}
5163

    
5164
/**
5165
 * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original,
5166
 * unmemoized form. Handy for testing.
5167
 *
5168
 * @name unmemoize
5169
 * @static
5170
 * @memberOf module:Utils
5171
 * @method
5172
 * @see [async.memoize]{@link module:Utils.memoize}
5173
 * @category Util
5174
 * @param {AsyncFunction} fn - the memoized function
5175
 * @returns {AsyncFunction} a function that calls the original unmemoized function
5176
 */
5177
function unmemoize(fn) {
5178
    return function () {
5179
        return (fn.unmemoized || fn).apply(null, arguments);
5180
    };
5181
}
5182

    
5183
/**
5184
 * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when
5185
 * stopped, or an error occurs.
5186
 *
5187
 * @name whilst
5188
 * @static
5189
 * @memberOf module:ControlFlow
5190
 * @method
5191
 * @category Control Flow
5192
 * @param {Function} test - synchronous truth test to perform before each
5193
 * execution of `iteratee`. Invoked with ().
5194
 * @param {AsyncFunction} iteratee - An async function which is called each time
5195
 * `test` passes. Invoked with (callback).
5196
 * @param {Function} [callback] - A callback which is called after the test
5197
 * function has failed and repeated execution of `iteratee` has stopped. `callback`
5198
 * will be passed an error and any arguments passed to the final `iteratee`'s
5199
 * callback. Invoked with (err, [results]);
5200
 * @returns undefined
5201
 * @example
5202
 *
5203
 * var count = 0;
5204
 * async.whilst(
5205
 *     function() { return count < 5; },
5206
 *     function(callback) {
5207
 *         count++;
5208
 *         setTimeout(function() {
5209
 *             callback(null, count);
5210
 *         }, 1000);
5211
 *     },
5212
 *     function (err, n) {
5213
 *         // 5 seconds have passed, n = 5
5214
 *     }
5215
 * );
5216
 */
5217
function whilst(test, iteratee, callback) {
5218
    callback = onlyOnce(callback || noop);
5219
    var _iteratee = wrapAsync(iteratee);
5220
    if (!test()) return callback(null);
5221
    var next = function(err/*, ...args*/) {
5222
        if (err) return callback(err);
5223
        if (test()) return _iteratee(next);
5224
        var args = slice(arguments, 1);
5225
        callback.apply(null, [null].concat(args));
5226
    };
5227
    _iteratee(next);
5228
}
5229

    
5230
/**
5231
 * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when
5232
 * stopped, or an error occurs. `callback` will be passed an error and any
5233
 * arguments passed to the final `iteratee`'s callback.
5234
 *
5235
 * The inverse of [whilst]{@link module:ControlFlow.whilst}.
5236
 *
5237
 * @name until
5238
 * @static
5239
 * @memberOf module:ControlFlow
5240
 * @method
5241
 * @see [async.whilst]{@link module:ControlFlow.whilst}
5242
 * @category Control Flow
5243
 * @param {Function} test - synchronous truth test to perform before each
5244
 * execution of `iteratee`. Invoked with ().
5245
 * @param {AsyncFunction} iteratee - An async function which is called each time
5246
 * `test` fails. Invoked with (callback).
5247
 * @param {Function} [callback] - A callback which is called after the test
5248
 * function has passed and repeated execution of `iteratee` has stopped. `callback`
5249
 * will be passed an error and any arguments passed to the final `iteratee`'s
5250
 * callback. Invoked with (err, [results]);
5251
 */
5252
function until(test, iteratee, callback) {
5253
    whilst(function() {
5254
        return !test.apply(this, arguments);
5255
    }, iteratee, callback);
5256
}
5257

    
5258
/**
5259
 * Runs the `tasks` array of functions in series, each passing their results to
5260
 * the next in the array. However, if any of the `tasks` pass an error to their
5261
 * own callback, the next function is not executed, and the main `callback` is
5262
 * immediately called with the error.
5263
 *
5264
 * @name waterfall
5265
 * @static
5266
 * @memberOf module:ControlFlow
5267
 * @method
5268
 * @category Control Flow
5269
 * @param {Array} tasks - An array of [async functions]{@link AsyncFunction}
5270
 * to run.
5271
 * Each function should complete with any number of `result` values.
5272
 * The `result` values will be passed as arguments, in order, to the next task.
5273
 * @param {Function} [callback] - An optional callback to run once all the
5274
 * functions have completed. This will be passed the results of the last task's
5275
 * callback. Invoked with (err, [results]).
5276
 * @returns undefined
5277
 * @example
5278
 *
5279
 * async.waterfall([
5280
 *     function(callback) {
5281
 *         callback(null, 'one', 'two');
5282
 *     },
5283
 *     function(arg1, arg2, callback) {
5284
 *         // arg1 now equals 'one' and arg2 now equals 'two'
5285
 *         callback(null, 'three');
5286
 *     },
5287
 *     function(arg1, callback) {
5288
 *         // arg1 now equals 'three'
5289
 *         callback(null, 'done');
5290
 *     }
5291
 * ], function (err, result) {
5292
 *     // result now equals 'done'
5293
 * });
5294
 *
5295
 * // Or, with named functions:
5296
 * async.waterfall([
5297
 *     myFirstFunction,
5298
 *     mySecondFunction,
5299
 *     myLastFunction,
5300
 * ], function (err, result) {
5301
 *     // result now equals 'done'
5302
 * });
5303
 * function myFirstFunction(callback) {
5304
 *     callback(null, 'one', 'two');
5305
 * }
5306
 * function mySecondFunction(arg1, arg2, callback) {
5307
 *     // arg1 now equals 'one' and arg2 now equals 'two'
5308
 *     callback(null, 'three');
5309
 * }
5310
 * function myLastFunction(arg1, callback) {
5311
 *     // arg1 now equals 'three'
5312
 *     callback(null, 'done');
5313
 * }
5314
 */
5315
var waterfall = function(tasks, callback) {
5316
    callback = once(callback || noop);
5317
    if (!isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions'));
5318
    if (!tasks.length) return callback();
5319
    var taskIndex = 0;
5320

    
5321
    function nextTask(args) {
5322
        var task = wrapAsync(tasks[taskIndex++]);
5323
        args.push(onlyOnce(next));
5324
        task.apply(null, args);
5325
    }
5326

    
5327
    function next(err/*, ...args*/) {
5328
        if (err || taskIndex === tasks.length) {
5329
            return callback.apply(null, arguments);
5330
        }
5331
        nextTask(slice(arguments, 1));
5332
    }
5333

    
5334
    nextTask([]);
5335
};
5336

    
5337
/**
5338
 * An "async function" in the context of Async is an asynchronous function with
5339
 * a variable number of parameters, with the final parameter being a callback.
5340
 * (`function (arg1, arg2, ..., callback) {}`)
5341
 * The final callback is of the form `callback(err, results...)`, which must be
5342
 * called once the function is completed.  The callback should be called with a
5343
 * Error as its first argument to signal that an error occurred.
5344
 * Otherwise, if no error occurred, it should be called with `null` as the first
5345
 * argument, and any additional `result` arguments that may apply, to signal
5346
 * successful completion.
5347
 * The callback must be called exactly once, ideally on a later tick of the
5348
 * JavaScript event loop.
5349
 *
5350
 * This type of function is also referred to as a "Node-style async function",
5351
 * or a "continuation passing-style function" (CPS). Most of the methods of this
5352
 * library are themselves CPS/Node-style async functions, or functions that
5353
 * return CPS/Node-style async functions.
5354
 *
5355
 * Wherever we accept a Node-style async function, we also directly accept an
5356
 * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}.
5357
 * In this case, the `async` function will not be passed a final callback
5358
 * argument, and any thrown error will be used as the `err` argument of the
5359
 * implicit callback, and the return value will be used as the `result` value.
5360
 * (i.e. a `rejected` of the returned Promise becomes the `err` callback
5361
 * argument, and a `resolved` value becomes the `result`.)
5362
 *
5363
 * Note, due to JavaScript limitations, we can only detect native `async`
5364
 * functions and not transpilied implementations.
5365
 * Your environment must have `async`/`await` support for this to work.
5366
 * (e.g. Node > v7.6, or a recent version of a modern browser).
5367
 * If you are using `async` functions through a transpiler (e.g. Babel), you
5368
 * must still wrap the function with [asyncify]{@link module:Utils.asyncify},
5369
 * because the `async function` will be compiled to an ordinary function that
5370
 * returns a promise.
5371
 *
5372
 * @typedef {Function} AsyncFunction
5373
 * @static
5374
 */
5375

    
5376
/**
5377
 * Async is a utility module which provides straight-forward, powerful functions
5378
 * for working with asynchronous JavaScript. Although originally designed for
5379
 * use with [Node.js](http://nodejs.org) and installable via
5380
 * `npm install --save async`, it can also be used directly in the browser.
5381
 * @module async
5382
 * @see AsyncFunction
5383
 */
5384

    
5385

    
5386
/**
5387
 * A collection of `async` functions for manipulating collections, such as
5388
 * arrays and objects.
5389
 * @module Collections
5390
 */
5391

    
5392
/**
5393
 * A collection of `async` functions for controlling the flow through a script.
5394
 * @module ControlFlow
5395
 */
5396

    
5397
/**
5398
 * A collection of `async` utility functions.
5399
 * @module Utils
5400
 */
5401

    
5402
var index = {
5403
    apply: apply,
5404
    applyEach: applyEach,
5405
    applyEachSeries: applyEachSeries,
5406
    asyncify: asyncify,
5407
    auto: auto,
5408
    autoInject: autoInject,
5409
    cargo: cargo,
5410
    compose: compose,
5411
    concat: concat,
5412
    concatLimit: concatLimit,
5413
    concatSeries: concatSeries,
5414
    constant: constant,
5415
    detect: detect,
5416
    detectLimit: detectLimit,
5417
    detectSeries: detectSeries,
5418
    dir: dir,
5419
    doDuring: doDuring,
5420
    doUntil: doUntil,
5421
    doWhilst: doWhilst,
5422
    during: during,
5423
    each: eachLimit,
5424
    eachLimit: eachLimit$1,
5425
    eachOf: eachOf,
5426
    eachOfLimit: eachOfLimit,
5427
    eachOfSeries: eachOfSeries,
5428
    eachSeries: eachSeries,
5429
    ensureAsync: ensureAsync,
5430
    every: every,
5431
    everyLimit: everyLimit,
5432
    everySeries: everySeries,
5433
    filter: filter,
5434
    filterLimit: filterLimit,
5435
    filterSeries: filterSeries,
5436
    forever: forever,
5437
    groupBy: groupBy,
5438
    groupByLimit: groupByLimit,
5439
    groupBySeries: groupBySeries,
5440
    log: log,
5441
    map: map,
5442
    mapLimit: mapLimit,
5443
    mapSeries: mapSeries,
5444
    mapValues: mapValues,
5445
    mapValuesLimit: mapValuesLimit,
5446
    mapValuesSeries: mapValuesSeries,
5447
    memoize: memoize,
5448
    nextTick: nextTick,
5449
    parallel: parallelLimit,
5450
    parallelLimit: parallelLimit$1,
5451
    priorityQueue: priorityQueue,
5452
    queue: queue$1,
5453
    race: race,
5454
    reduce: reduce,
5455
    reduceRight: reduceRight,
5456
    reflect: reflect,
5457
    reflectAll: reflectAll,
5458
    reject: reject,
5459
    rejectLimit: rejectLimit,
5460
    rejectSeries: rejectSeries,
5461
    retry: retry,
5462
    retryable: retryable,
5463
    seq: seq,
5464
    series: series,
5465
    setImmediate: setImmediate$1,
5466
    some: some,
5467
    someLimit: someLimit,
5468
    someSeries: someSeries,
5469
    sortBy: sortBy,
5470
    timeout: timeout,
5471
    times: times,
5472
    timesLimit: timeLimit,
5473
    timesSeries: timesSeries,
5474
    transform: transform,
5475
    tryEach: tryEach,
5476
    unmemoize: unmemoize,
5477
    until: until,
5478
    waterfall: waterfall,
5479
    whilst: whilst,
5480

    
5481
    // aliases
5482
    all: every,
5483
    allLimit: everyLimit,
5484
    allSeries: everySeries,
5485
    any: some,
5486
    anyLimit: someLimit,
5487
    anySeries: someSeries,
5488
    find: detect,
5489
    findLimit: detectLimit,
5490
    findSeries: detectSeries,
5491
    forEach: eachLimit,
5492
    forEachSeries: eachSeries,
5493
    forEachLimit: eachLimit$1,
5494
    forEachOf: eachOf,
5495
    forEachOfSeries: eachOfSeries,
5496
    forEachOfLimit: eachOfLimit,
5497
    inject: reduce,
5498
    foldl: reduce,
5499
    foldr: reduceRight,
5500
    select: filter,
5501
    selectLimit: filterLimit,
5502
    selectSeries: filterSeries,
5503
    wrapSync: asyncify
5504
};
5505

    
5506
exports['default'] = index;
5507
exports.apply = apply;
5508
exports.applyEach = applyEach;
5509
exports.applyEachSeries = applyEachSeries;
5510
exports.asyncify = asyncify;
5511
exports.auto = auto;
5512
exports.autoInject = autoInject;
5513
exports.cargo = cargo;
5514
exports.compose = compose;
5515
exports.concat = concat;
5516
exports.concatLimit = concatLimit;
5517
exports.concatSeries = concatSeries;
5518
exports.constant = constant;
5519
exports.detect = detect;
5520
exports.detectLimit = detectLimit;
5521
exports.detectSeries = detectSeries;
5522
exports.dir = dir;
5523
exports.doDuring = doDuring;
5524
exports.doUntil = doUntil;
5525
exports.doWhilst = doWhilst;
5526
exports.during = during;
5527
exports.each = eachLimit;
5528
exports.eachLimit = eachLimit$1;
5529
exports.eachOf = eachOf;
5530
exports.eachOfLimit = eachOfLimit;
5531
exports.eachOfSeries = eachOfSeries;
5532
exports.eachSeries = eachSeries;
5533
exports.ensureAsync = ensureAsync;
5534
exports.every = every;
5535
exports.everyLimit = everyLimit;
5536
exports.everySeries = everySeries;
5537
exports.filter = filter;
5538
exports.filterLimit = filterLimit;
5539
exports.filterSeries = filterSeries;
5540
exports.forever = forever;
5541
exports.groupBy = groupBy;
5542
exports.groupByLimit = groupByLimit;
5543
exports.groupBySeries = groupBySeries;
5544
exports.log = log;
5545
exports.map = map;
5546
exports.mapLimit = mapLimit;
5547
exports.mapSeries = mapSeries;
5548
exports.mapValues = mapValues;
5549
exports.mapValuesLimit = mapValuesLimit;
5550
exports.mapValuesSeries = mapValuesSeries;
5551
exports.memoize = memoize;
5552
exports.nextTick = nextTick;
5553
exports.parallel = parallelLimit;
5554
exports.parallelLimit = parallelLimit$1;
5555
exports.priorityQueue = priorityQueue;
5556
exports.queue = queue$1;
5557
exports.race = race;
5558
exports.reduce = reduce;
5559
exports.reduceRight = reduceRight;
5560
exports.reflect = reflect;
5561
exports.reflectAll = reflectAll;
5562
exports.reject = reject;
5563
exports.rejectLimit = rejectLimit;
5564
exports.rejectSeries = rejectSeries;
5565
exports.retry = retry;
5566
exports.retryable = retryable;
5567
exports.seq = seq;
5568
exports.series = series;
5569
exports.setImmediate = setImmediate$1;
5570
exports.some = some;
5571
exports.someLimit = someLimit;
5572
exports.someSeries = someSeries;
5573
exports.sortBy = sortBy;
5574
exports.timeout = timeout;
5575
exports.times = times;
5576
exports.timesLimit = timeLimit;
5577
exports.timesSeries = timesSeries;
5578
exports.transform = transform;
5579
exports.tryEach = tryEach;
5580
exports.unmemoize = unmemoize;
5581
exports.until = until;
5582
exports.waterfall = waterfall;
5583
exports.whilst = whilst;
5584
exports.all = every;
5585
exports.allLimit = everyLimit;
5586
exports.allSeries = everySeries;
5587
exports.any = some;
5588
exports.anyLimit = someLimit;
5589
exports.anySeries = someSeries;
5590
exports.find = detect;
5591
exports.findLimit = detectLimit;
5592
exports.findSeries = detectSeries;
5593
exports.forEach = eachLimit;
5594
exports.forEachSeries = eachSeries;
5595
exports.forEachLimit = eachLimit$1;
5596
exports.forEachOf = eachOf;
5597
exports.forEachOfSeries = eachOfSeries;
5598
exports.forEachOfLimit = eachOfLimit;
5599
exports.inject = reduce;
5600
exports.foldl = reduce;
5601
exports.foldr = reduceRight;
5602
exports.select = filter;
5603
exports.selectLimit = filterLimit;
5604
exports.selectSeries = filterSeries;
5605
exports.wrapSync = asyncify;
5606

    
5607
Object.defineProperty(exports, '__esModule', { value: true });
5608

    
5609
})));
(1-1/3)