UNPKG

165 kBJavaScriptView Raw
1/**
2 * Creates a continuation function with some arguments already applied.
3 *
4 * Useful as a shorthand when combined with other control flow functions. Any
5 * arguments passed to the returned function are added to the arguments
6 * originally passed to apply.
7 *
8 * @name apply
9 * @static
10 * @memberOf module:Utils
11 * @method
12 * @category Util
13 * @param {Function} fn - The function you want to eventually apply all
14 * arguments to. Invokes with (arguments...).
15 * @param {...*} arguments... - Any number of arguments to automatically apply
16 * when the continuation is called.
17 * @returns {Function} the partially-applied function
18 * @example
19 *
20 * // using apply
21 * async.parallel([
22 * async.apply(fs.writeFile, 'testfile1', 'test1'),
23 * async.apply(fs.writeFile, 'testfile2', 'test2')
24 * ]);
25 *
26 *
27 * // the same process without using apply
28 * async.parallel([
29 * function(callback) {
30 * fs.writeFile('testfile1', 'test1', callback);
31 * },
32 * function(callback) {
33 * fs.writeFile('testfile2', 'test2', callback);
34 * }
35 * ]);
36 *
37 * // It's possible to pass any number of additional arguments when calling the
38 * // continuation:
39 *
40 * node> var fn = async.apply(sys.puts, 'one');
41 * node> fn('two', 'three');
42 * one
43 * two
44 * three
45 */
46function apply(fn, ...args) {
47 return (...callArgs) => fn(...args,...callArgs);
48}
49
50function initialParams (fn) {
51 return function (...args/*, callback*/) {
52 var callback = args.pop();
53 return fn.call(this, args, callback);
54 };
55}
56
57/* istanbul ignore file */
58
59var hasSetImmediate = typeof setImmediate === 'function' && setImmediate;
60var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function';
61
62function fallback(fn) {
63 setTimeout(fn, 0);
64}
65
66function wrap(defer) {
67 return (fn, ...args) => defer(() => fn(...args));
68}
69
70var _defer;
71
72if (hasSetImmediate) {
73 _defer = setImmediate;
74} else if (hasNextTick) {
75 _defer = process.nextTick;
76} else {
77 _defer = fallback;
78}
79
80var setImmediate$1 = wrap(_defer);
81
82/**
83 * Take a sync function and make it async, passing its return value to a
84 * callback. This is useful for plugging sync functions into a waterfall,
85 * series, or other async functions. Any arguments passed to the generated
86 * function will be passed to the wrapped function (except for the final
87 * callback argument). Errors thrown will be passed to the callback.
88 *
89 * If the function passed to `asyncify` returns a Promise, that promises's
90 * resolved/rejected state will be used to call the callback, rather than simply
91 * the synchronous return value.
92 *
93 * This also means you can asyncify ES2017 `async` functions.
94 *
95 * @name asyncify
96 * @static
97 * @memberOf module:Utils
98 * @method
99 * @alias wrapSync
100 * @category Util
101 * @param {Function} func - The synchronous function, or Promise-returning
102 * function to convert to an {@link AsyncFunction}.
103 * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
104 * invoked with `(args..., callback)`.
105 * @example
106 *
107 * // passing a regular synchronous function
108 * async.waterfall([
109 * async.apply(fs.readFile, filename, "utf8"),
110 * async.asyncify(JSON.parse),
111 * function (data, next) {
112 * // data is the result of parsing the text.
113 * // If there was a parsing error, it would have been caught.
114 * }
115 * ], callback);
116 *
117 * // passing a function returning a promise
118 * async.waterfall([
119 * async.apply(fs.readFile, filename, "utf8"),
120 * async.asyncify(function (contents) {
121 * return db.model.create(contents);
122 * }),
123 * function (model, next) {
124 * // `model` is the instantiated model object.
125 * // If there was an error, this function would be skipped.
126 * }
127 * ], callback);
128 *
129 * // es2017 example, though `asyncify` is not needed if your JS environment
130 * // supports async functions out of the box
131 * var q = async.queue(async.asyncify(async function(file) {
132 * var intermediateStep = await processFile(file);
133 * return await somePromise(intermediateStep)
134 * }));
135 *
136 * q.push(files);
137 */
138function asyncify(func) {
139 if (isAsync(func)) {
140 return function (...args/*, callback*/) {
141 const callback = args.pop();
142 const promise = func.apply(this, args);
143 return handlePromise(promise, callback)
144 }
145 }
146
147 return initialParams(function (args, callback) {
148 var result;
149 try {
150 result = func.apply(this, args);
151 } catch (e) {
152 return callback(e);
153 }
154 // if result is Promise object
155 if (result && typeof result.then === 'function') {
156 return handlePromise(result, callback)
157 } else {
158 callback(null, result);
159 }
160 });
161}
162
163function handlePromise(promise, callback) {
164 return promise.then(value => {
165 invokeCallback(callback, null, value);
166 }, err => {
167 invokeCallback(callback, err && err.message ? err : new Error(err));
168 });
169}
170
171function invokeCallback(callback, error, value) {
172 try {
173 callback(error, value);
174 } catch (err) {
175 setImmediate$1(e => { throw e }, err);
176 }
177}
178
179function isAsync(fn) {
180 return fn[Symbol.toStringTag] === 'AsyncFunction';
181}
182
183function isAsyncGenerator(fn) {
184 return fn[Symbol.toStringTag] === 'AsyncGenerator';
185}
186
187function isAsyncIterable(obj) {
188 return typeof obj[Symbol.asyncIterator] === 'function';
189}
190
191function wrapAsync(asyncFn) {
192 if (typeof asyncFn !== 'function') throw new Error('expected a function')
193 return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn;
194}
195
196// conditionally promisify a function.
197// only return a promise if a callback is omitted
198function awaitify (asyncFn, arity = asyncFn.length) {
199 if (!arity) throw new Error('arity is undefined')
200 function awaitable (...args) {
201 if (typeof args[arity - 1] === 'function') {
202 return asyncFn.apply(this, args)
203 }
204
205 return new Promise((resolve, reject) => {
206 args[arity - 1] = (err, ...cbArgs) => {
207 if (err) return reject(err)
208 resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
209 };
210 asyncFn.apply(this, args);
211 })
212 }
213
214 return awaitable
215}
216
217function applyEach (eachfn) {
218 return function applyEach(fns, ...callArgs) {
219 const go = awaitify(function (callback) {
220 var that = this;
221 return eachfn(fns, (fn, cb) => {
222 wrapAsync(fn).apply(that, callArgs.concat(cb));
223 }, callback);
224 });
225 return go;
226 };
227}
228
229function _asyncMap(eachfn, arr, iteratee, callback) {
230 arr = arr || [];
231 var results = [];
232 var counter = 0;
233 var _iteratee = wrapAsync(iteratee);
234
235 return eachfn(arr, (value, _, iterCb) => {
236 var index = counter++;
237 _iteratee(value, (err, v) => {
238 results[index] = v;
239 iterCb(err);
240 });
241 }, err => {
242 callback(err, results);
243 });
244}
245
246function isArrayLike(value) {
247 return value &&
248 typeof value.length === 'number' &&
249 value.length >= 0 &&
250 value.length % 1 === 0;
251}
252
253// A temporary value used to identify if the loop should be broken.
254// See #1064, #1293
255const breakLoop = {};
256
257function once(fn) {
258 function wrapper (...args) {
259 if (fn === null) return;
260 var callFn = fn;
261 fn = null;
262 callFn.apply(this, args);
263 }
264 Object.assign(wrapper, fn);
265 return wrapper
266}
267
268function getIterator (coll) {
269 return coll[Symbol.iterator] && coll[Symbol.iterator]();
270}
271
272function createArrayIterator(coll) {
273 var i = -1;
274 var len = coll.length;
275 return function next() {
276 return ++i < len ? {value: coll[i], key: i} : null;
277 }
278}
279
280function createES2015Iterator(iterator) {
281 var i = -1;
282 return function next() {
283 var item = iterator.next();
284 if (item.done)
285 return null;
286 i++;
287 return {value: item.value, key: i};
288 }
289}
290
291function createObjectIterator(obj) {
292 var okeys = obj ? Object.keys(obj) : [];
293 var i = -1;
294 var len = okeys.length;
295 return function next() {
296 var key = okeys[++i];
297 return i < len ? {value: obj[key], key} : null;
298 };
299}
300
301function createIterator(coll) {
302 if (isArrayLike(coll)) {
303 return createArrayIterator(coll);
304 }
305
306 var iterator = getIterator(coll);
307 return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll);
308}
309
310function onlyOnce(fn) {
311 return function (...args) {
312 if (fn === null) throw new Error("Callback was already called.");
313 var callFn = fn;
314 fn = null;
315 callFn.apply(this, args);
316 };
317}
318
319// for async generators
320function asyncEachOfLimit(generator, limit, iteratee, callback) {
321 let done = false;
322 let canceled = false;
323 let awaiting = false;
324 let running = 0;
325 let idx = 0;
326
327 function replenish() {
328 //console.log('replenish')
329 if (running >= limit || awaiting || done) return
330 //console.log('replenish awaiting')
331 awaiting = true;
332 generator.next().then(({value, done: iterDone}) => {
333 //console.log('got value', value)
334 if (canceled || done) return
335 awaiting = false;
336 if (iterDone) {
337 done = true;
338 if (running <= 0) {
339 //console.log('done nextCb')
340 callback(null);
341 }
342 return;
343 }
344 running++;
345 iteratee(value, idx, iterateeCallback);
346 idx++;
347 replenish();
348 }).catch(handleError);
349 }
350
351 function iterateeCallback(err, result) {
352 //console.log('iterateeCallback')
353 running -= 1;
354 if (canceled) return
355 if (err) return handleError(err)
356
357 if (err === false) {
358 done = true;
359 canceled = true;
360 return
361 }
362
363 if (result === breakLoop || (done && running <= 0)) {
364 done = true;
365 //console.log('done iterCb')
366 return callback(null);
367 }
368 replenish();
369 }
370
371 function handleError(err) {
372 if (canceled) return
373 awaiting = false;
374 done = true;
375 callback(err);
376 }
377
378 replenish();
379}
380
381var eachOfLimit = (limit) => {
382 return (obj, iteratee, callback) => {
383 callback = once(callback);
384 if (limit <= 0) {
385 throw new RangeError('concurrency limit cannot be less than 1')
386 }
387 if (!obj) {
388 return callback(null);
389 }
390 if (isAsyncGenerator(obj)) {
391 return asyncEachOfLimit(obj, limit, iteratee, callback)
392 }
393 if (isAsyncIterable(obj)) {
394 return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback)
395 }
396 var nextElem = createIterator(obj);
397 var done = false;
398 var canceled = false;
399 var running = 0;
400 var looping = false;
401
402 function iterateeCallback(err, value) {
403 if (canceled) return
404 running -= 1;
405 if (err) {
406 done = true;
407 callback(err);
408 }
409 else if (err === false) {
410 done = true;
411 canceled = true;
412 }
413 else if (value === breakLoop || (done && running <= 0)) {
414 done = true;
415 return callback(null);
416 }
417 else if (!looping) {
418 replenish();
419 }
420 }
421
422 function replenish () {
423 looping = true;
424 while (running < limit && !done) {
425 var elem = nextElem();
426 if (elem === null) {
427 done = true;
428 if (running <= 0) {
429 callback(null);
430 }
431 return;
432 }
433 running += 1;
434 iteratee(elem.value, elem.key, onlyOnce(iterateeCallback));
435 }
436 looping = false;
437 }
438
439 replenish();
440 };
441};
442
443/**
444 * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
445 * time.
446 *
447 * @name eachOfLimit
448 * @static
449 * @memberOf module:Collections
450 * @method
451 * @see [async.eachOf]{@link module:Collections.eachOf}
452 * @alias forEachOfLimit
453 * @category Collection
454 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
455 * @param {number} limit - The maximum number of async operations at a time.
456 * @param {AsyncFunction} iteratee - An async function to apply to each
457 * item in `coll`. The `key` is the item's key, or index in the case of an
458 * array.
459 * Invoked with (item, key, callback).
460 * @param {Function} [callback] - A callback which is called when all
461 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
462 * @returns {Promise} a promise, if a callback is omitted
463 */
464function eachOfLimit$1(coll, limit, iteratee, callback) {
465 return eachOfLimit(limit)(coll, wrapAsync(iteratee), callback);
466}
467
468var eachOfLimit$2 = awaitify(eachOfLimit$1, 4);
469
470// eachOf implementation optimized for array-likes
471function eachOfArrayLike(coll, iteratee, callback) {
472 callback = once(callback);
473 var index = 0,
474 completed = 0,
475 {length} = coll,
476 canceled = false;
477 if (length === 0) {
478 callback(null);
479 }
480
481 function iteratorCallback(err, value) {
482 if (err === false) {
483 canceled = true;
484 }
485 if (canceled === true) return
486 if (err) {
487 callback(err);
488 } else if ((++completed === length) || value === breakLoop) {
489 callback(null);
490 }
491 }
492
493 for (; index < length; index++) {
494 iteratee(coll[index], index, onlyOnce(iteratorCallback));
495 }
496}
497
498// a generic version of eachOf which can handle array, object, and iterator cases.
499function eachOfGeneric (coll, iteratee, callback) {
500 return eachOfLimit$2(coll, Infinity, iteratee, callback);
501}
502
503/**
504 * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument
505 * to the iteratee.
506 *
507 * @name eachOf
508 * @static
509 * @memberOf module:Collections
510 * @method
511 * @alias forEachOf
512 * @category Collection
513 * @see [async.each]{@link module:Collections.each}
514 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
515 * @param {AsyncFunction} iteratee - A function to apply to each
516 * item in `coll`.
517 * The `key` is the item's key, or index in the case of an array.
518 * Invoked with (item, key, callback).
519 * @param {Function} [callback] - A callback which is called when all
520 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
521 * @returns {Promise} a promise, if a callback is omitted
522 * @example
523 *
524 * var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
525 * var configs = {};
526 *
527 * async.forEachOf(obj, function (value, key, callback) {
528 * fs.readFile(__dirname + value, "utf8", function (err, data) {
529 * if (err) return callback(err);
530 * try {
531 * configs[key] = JSON.parse(data);
532 * } catch (e) {
533 * return callback(e);
534 * }
535 * callback();
536 * });
537 * }, function (err) {
538 * if (err) console.error(err.message);
539 * // configs is now a map of JSON data
540 * doSomethingWith(configs);
541 * });
542 */
543function eachOf(coll, iteratee, callback) {
544 var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric;
545 return eachOfImplementation(coll, wrapAsync(iteratee), callback);
546}
547
548var eachOf$1 = awaitify(eachOf, 3);
549
550/**
551 * Produces a new collection of values by mapping each value in `coll` through
552 * the `iteratee` function. The `iteratee` is called with an item from `coll`
553 * and a callback for when it has finished processing. Each of these callback
554 * takes 2 arguments: an `error`, and the transformed item from `coll`. If
555 * `iteratee` passes an error to its callback, the main `callback` (for the
556 * `map` function) is immediately called with the error.
557 *
558 * Note, that since this function applies the `iteratee` to each item in
559 * parallel, there is no guarantee that the `iteratee` functions will complete
560 * in order. However, the results array will be in the same order as the
561 * original `coll`.
562 *
563 * If `map` is passed an Object, the results will be an Array. The results
564 * will roughly be in the order of the original Objects' keys (but this can
565 * vary across JavaScript engines).
566 *
567 * @name map
568 * @static
569 * @memberOf module:Collections
570 * @method
571 * @category Collection
572 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
573 * @param {AsyncFunction} iteratee - An async function to apply to each item in
574 * `coll`.
575 * The iteratee should complete with the transformed item.
576 * Invoked with (item, callback).
577 * @param {Function} [callback] - A callback which is called when all `iteratee`
578 * functions have finished, or an error occurs. Results is an Array of the
579 * transformed items from the `coll`. Invoked with (err, results).
580 * @returns {Promise} a promise, if no callback is passed
581 * @example
582 *
583 * async.map(['file1','file2','file3'], fs.stat, function(err, results) {
584 * // results is now an array of stats for each file
585 * });
586 */
587function map (coll, iteratee, callback) {
588 return _asyncMap(eachOf$1, coll, iteratee, callback)
589}
590var map$1 = awaitify(map, 3);
591
592/**
593 * Applies the provided arguments to each function in the array, calling
594 * `callback` after all functions have completed. If you only provide the first
595 * argument, `fns`, then it will return a function which lets you pass in the
596 * arguments as if it were a single function call. If more arguments are
597 * provided, `callback` is required while `args` is still optional. The results
598 * for each of the applied async functions are passed to the final callback
599 * as an array.
600 *
601 * @name applyEach
602 * @static
603 * @memberOf module:ControlFlow
604 * @method
605 * @category Control Flow
606 * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s
607 * to all call with the same arguments
608 * @param {...*} [args] - any number of separate arguments to pass to the
609 * function.
610 * @param {Function} [callback] - the final argument should be the callback,
611 * called when all functions have completed processing.
612 * @returns {AsyncFunction} - Returns a function that takes no args other than
613 * an optional callback, that is the result of applying the `args` to each
614 * of the functions.
615 * @example
616 *
617 * const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket')
618 *
619 * appliedFn((err, results) => {
620 * // results[0] is the results for `enableSearch`
621 * // results[1] is the results for `updateSchema`
622 * });
623 *
624 * // partial application example:
625 * async.each(
626 * buckets,
627 * async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(),
628 * callback
629 * );
630 */
631var applyEach$1 = applyEach(map$1);
632
633/**
634 * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
635 *
636 * @name eachOfSeries
637 * @static
638 * @memberOf module:Collections
639 * @method
640 * @see [async.eachOf]{@link module:Collections.eachOf}
641 * @alias forEachOfSeries
642 * @category Collection
643 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
644 * @param {AsyncFunction} iteratee - An async function to apply to each item in
645 * `coll`.
646 * Invoked with (item, key, callback).
647 * @param {Function} [callback] - A callback which is called when all `iteratee`
648 * functions have finished, or an error occurs. Invoked with (err).
649 * @returns {Promise} a promise, if a callback is omitted
650 */
651function eachOfSeries(coll, iteratee, callback) {
652 return eachOfLimit$2(coll, 1, iteratee, callback)
653}
654var eachOfSeries$1 = awaitify(eachOfSeries, 3);
655
656/**
657 * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time.
658 *
659 * @name mapSeries
660 * @static
661 * @memberOf module:Collections
662 * @method
663 * @see [async.map]{@link module:Collections.map}
664 * @category Collection
665 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
666 * @param {AsyncFunction} iteratee - An async function to apply to each item in
667 * `coll`.
668 * The iteratee should complete with the transformed item.
669 * Invoked with (item, callback).
670 * @param {Function} [callback] - A callback which is called when all `iteratee`
671 * functions have finished, or an error occurs. Results is an array of the
672 * transformed items from the `coll`. Invoked with (err, results).
673 * @returns {Promise} a promise, if no callback is passed
674 */
675function mapSeries (coll, iteratee, callback) {
676 return _asyncMap(eachOfSeries$1, coll, iteratee, callback)
677}
678var mapSeries$1 = awaitify(mapSeries, 3);
679
680/**
681 * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time.
682 *
683 * @name applyEachSeries
684 * @static
685 * @memberOf module:ControlFlow
686 * @method
687 * @see [async.applyEach]{@link module:ControlFlow.applyEach}
688 * @category Control Flow
689 * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s to all
690 * call with the same arguments
691 * @param {...*} [args] - any number of separate arguments to pass to the
692 * function.
693 * @param {Function} [callback] - the final argument should be the callback,
694 * called when all functions have completed processing.
695 * @returns {AsyncFunction} - A function, that when called, is the result of
696 * appling the `args` to the list of functions. It takes no args, other than
697 * a callback.
698 */
699var applyEachSeries = applyEach(mapSeries$1);
700
701const PROMISE_SYMBOL = Symbol('promiseCallback');
702
703function promiseCallback () {
704 let resolve, reject;
705 function callback (err, ...args) {
706 if (err) return reject(err)
707 resolve(args.length > 1 ? args : args[0]);
708 }
709
710 callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
711 resolve = res,
712 reject = rej;
713 });
714
715 return callback
716}
717
718/**
719 * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on
720 * their requirements. Each function can optionally depend on other functions
721 * being completed first, and each function is run as soon as its requirements
722 * are satisfied.
723 *
724 * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence
725 * will stop. Further tasks will not execute (so any other functions depending
726 * on it will not run), and the main `callback` is immediately called with the
727 * error.
728 *
729 * {@link AsyncFunction}s also receive an object containing the results of functions which
730 * have completed so far as the first argument, if they have dependencies. If a
731 * task function has no dependencies, it will only be passed a callback.
732 *
733 * @name auto
734 * @static
735 * @memberOf module:ControlFlow
736 * @method
737 * @category Control Flow
738 * @param {Object} tasks - An object. Each of its properties is either a
739 * function or an array of requirements, with the {@link AsyncFunction} itself the last item
740 * in the array. The object's key of a property serves as the name of the task
741 * defined by that property, i.e. can be used when specifying requirements for
742 * other tasks. The function receives one or two arguments:
743 * * a `results` object, containing the results of the previously executed
744 * functions, only passed if the task has any dependencies,
745 * * a `callback(err, result)` function, which must be called when finished,
746 * passing an `error` (which can be `null`) and the result of the function's
747 * execution.
748 * @param {number} [concurrency=Infinity] - An optional `integer` for
749 * determining the maximum number of tasks that can be run in parallel. By
750 * default, as many as possible.
751 * @param {Function} [callback] - An optional callback which is called when all
752 * the tasks have been completed. It receives the `err` argument if any `tasks`
753 * pass an error to their callback. Results are always returned; however, if an
754 * error occurs, no further `tasks` will be performed, and the results object
755 * will only contain partial results. Invoked with (err, results).
756 * @returns {Promise} a promise, if a callback is not passed
757 * @example
758 *
759 * async.auto({
760 * // this function will just be passed a callback
761 * readData: async.apply(fs.readFile, 'data.txt', 'utf-8'),
762 * showData: ['readData', function(results, cb) {
763 * // results.readData is the file's contents
764 * // ...
765 * }]
766 * }, callback);
767 *
768 * async.auto({
769 * get_data: function(callback) {
770 * console.log('in get_data');
771 * // async code to get some data
772 * callback(null, 'data', 'converted to array');
773 * },
774 * make_folder: function(callback) {
775 * console.log('in make_folder');
776 * // async code to create a directory to store a file in
777 * // this is run at the same time as getting the data
778 * callback(null, 'folder');
779 * },
780 * write_file: ['get_data', 'make_folder', function(results, callback) {
781 * console.log('in write_file', JSON.stringify(results));
782 * // once there is some data and the directory exists,
783 * // write the data to a file in the directory
784 * callback(null, 'filename');
785 * }],
786 * email_link: ['write_file', function(results, callback) {
787 * console.log('in email_link', JSON.stringify(results));
788 * // once the file is written let's email a link to it...
789 * // results.write_file contains the filename returned by write_file.
790 * callback(null, {'file':results.write_file, 'email':'user@example.com'});
791 * }]
792 * }, function(err, results) {
793 * console.log('err = ', err);
794 * console.log('results = ', results);
795 * });
796 */
797function auto(tasks, concurrency, callback) {
798 if (typeof concurrency !== 'number') {
799 // concurrency is optional, shift the args.
800 callback = concurrency;
801 concurrency = null;
802 }
803 callback = once(callback || promiseCallback());
804 var numTasks = Object.keys(tasks).length;
805 if (!numTasks) {
806 return callback(null);
807 }
808 if (!concurrency) {
809 concurrency = numTasks;
810 }
811
812 var results = {};
813 var runningTasks = 0;
814 var canceled = false;
815 var hasError = false;
816
817 var listeners = Object.create(null);
818
819 var readyTasks = [];
820
821 // for cycle detection:
822 var readyToCheck = []; // tasks that have been identified as reachable
823 // without the possibility of returning to an ancestor task
824 var uncheckedDependencies = {};
825
826 Object.keys(tasks).forEach(key => {
827 var task = tasks[key];
828 if (!Array.isArray(task)) {
829 // no dependencies
830 enqueueTask(key, [task]);
831 readyToCheck.push(key);
832 return;
833 }
834
835 var dependencies = task.slice(0, task.length - 1);
836 var remainingDependencies = dependencies.length;
837 if (remainingDependencies === 0) {
838 enqueueTask(key, task);
839 readyToCheck.push(key);
840 return;
841 }
842 uncheckedDependencies[key] = remainingDependencies;
843
844 dependencies.forEach(dependencyName => {
845 if (!tasks[dependencyName]) {
846 throw new Error('async.auto task `' + key +
847 '` has a non-existent dependency `' +
848 dependencyName + '` in ' +
849 dependencies.join(', '));
850 }
851 addListener(dependencyName, () => {
852 remainingDependencies--;
853 if (remainingDependencies === 0) {
854 enqueueTask(key, task);
855 }
856 });
857 });
858 });
859
860 checkForDeadlocks();
861 processQueue();
862
863 function enqueueTask(key, task) {
864 readyTasks.push(() => runTask(key, task));
865 }
866
867 function processQueue() {
868 if (canceled) return
869 if (readyTasks.length === 0 && runningTasks === 0) {
870 return callback(null, results);
871 }
872 while(readyTasks.length && runningTasks < concurrency) {
873 var run = readyTasks.shift();
874 run();
875 }
876
877 }
878
879 function addListener(taskName, fn) {
880 var taskListeners = listeners[taskName];
881 if (!taskListeners) {
882 taskListeners = listeners[taskName] = [];
883 }
884
885 taskListeners.push(fn);
886 }
887
888 function taskComplete(taskName) {
889 var taskListeners = listeners[taskName] || [];
890 taskListeners.forEach(fn => fn());
891 processQueue();
892 }
893
894
895 function runTask(key, task) {
896 if (hasError) return;
897
898 var taskCallback = onlyOnce((err, ...result) => {
899 runningTasks--;
900 if (err === false) {
901 canceled = true;
902 return
903 }
904 if (result.length < 2) {
905 [result] = result;
906 }
907 if (err) {
908 var safeResults = {};
909 Object.keys(results).forEach(rkey => {
910 safeResults[rkey] = results[rkey];
911 });
912 safeResults[key] = result;
913 hasError = true;
914 listeners = Object.create(null);
915 if (canceled) return
916 callback(err, safeResults);
917 } else {
918 results[key] = result;
919 taskComplete(key);
920 }
921 });
922
923 runningTasks++;
924 var taskFn = wrapAsync(task[task.length - 1]);
925 if (task.length > 1) {
926 taskFn(results, taskCallback);
927 } else {
928 taskFn(taskCallback);
929 }
930 }
931
932 function checkForDeadlocks() {
933 // Kahn's algorithm
934 // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
935 // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html
936 var currentTask;
937 var counter = 0;
938 while (readyToCheck.length) {
939 currentTask = readyToCheck.pop();
940 counter++;
941 getDependents(currentTask).forEach(dependent => {
942 if (--uncheckedDependencies[dependent] === 0) {
943 readyToCheck.push(dependent);
944 }
945 });
946 }
947
948 if (counter !== numTasks) {
949 throw new Error(
950 'async.auto cannot execute tasks due to a recursive dependency'
951 );
952 }
953 }
954
955 function getDependents(taskName) {
956 var result = [];
957 Object.keys(tasks).forEach(key => {
958 const task = tasks[key];
959 if (Array.isArray(task) && task.indexOf(taskName) >= 0) {
960 result.push(key);
961 }
962 });
963 return result;
964 }
965
966 return callback[PROMISE_SYMBOL]
967}
968
969var FN_ARGS = /^(?:async\s+)?(?:function)?\s*\w*\s*\(\s*([^)]+)\s*\)(?:\s*{)/;
970var ARROW_FN_ARGS = /^(?:async\s+)?\(?\s*([^)=]+)\s*\)?(?:\s*=>)/;
971var FN_ARG_SPLIT = /,/;
972var FN_ARG = /(=.+)?(\s*)$/;
973var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
974
975function parseParams(func) {
976 const src = func.toString().replace(STRIP_COMMENTS, '');
977 let match = src.match(FN_ARGS);
978 if (!match) {
979 match = src.match(ARROW_FN_ARGS);
980 }
981 if (!match) throw new Error('could not parse args in autoInject\nSource:\n' + src)
982 let [, args] = match;
983 return args
984 .replace(/\s/g, '')
985 .split(FN_ARG_SPLIT)
986 .map((arg) => arg.replace(FN_ARG, '').trim());
987}
988
989/**
990 * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent
991 * tasks are specified as parameters to the function, after the usual callback
992 * parameter, with the parameter names matching the names of the tasks it
993 * depends on. This can provide even more readable task graphs which can be
994 * easier to maintain.
995 *
996 * If a final callback is specified, the task results are similarly injected,
997 * specified as named parameters after the initial error parameter.
998 *
999 * The autoInject function is purely syntactic sugar and its semantics are
1000 * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}.
1001 *
1002 * @name autoInject
1003 * @static
1004 * @memberOf module:ControlFlow
1005 * @method
1006 * @see [async.auto]{@link module:ControlFlow.auto}
1007 * @category Control Flow
1008 * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of
1009 * the form 'func([dependencies...], callback). The object's key of a property
1010 * serves as the name of the task defined by that property, i.e. can be used
1011 * when specifying requirements for other tasks.
1012 * * The `callback` parameter is a `callback(err, result)` which must be called
1013 * when finished, passing an `error` (which can be `null`) and the result of
1014 * the function's execution. The remaining parameters name other tasks on
1015 * which the task is dependent, and the results from those tasks are the
1016 * arguments of those parameters.
1017 * @param {Function} [callback] - An optional callback which is called when all
1018 * the tasks have been completed. It receives the `err` argument if any `tasks`
1019 * pass an error to their callback, and a `results` object with any completed
1020 * task results, similar to `auto`.
1021 * @returns {Promise} a promise, if no callback is passed
1022 * @example
1023 *
1024 * // The example from `auto` can be rewritten as follows:
1025 * async.autoInject({
1026 * get_data: function(callback) {
1027 * // async code to get some data
1028 * callback(null, 'data', 'converted to array');
1029 * },
1030 * make_folder: function(callback) {
1031 * // async code to create a directory to store a file in
1032 * // this is run at the same time as getting the data
1033 * callback(null, 'folder');
1034 * },
1035 * write_file: function(get_data, make_folder, callback) {
1036 * // once there is some data and the directory exists,
1037 * // write the data to a file in the directory
1038 * callback(null, 'filename');
1039 * },
1040 * email_link: function(write_file, callback) {
1041 * // once the file is written let's email a link to it...
1042 * // write_file contains the filename returned by write_file.
1043 * callback(null, {'file':write_file, 'email':'user@example.com'});
1044 * }
1045 * }, function(err, results) {
1046 * console.log('err = ', err);
1047 * console.log('email_link = ', results.email_link);
1048 * });
1049 *
1050 * // If you are using a JS minifier that mangles parameter names, `autoInject`
1051 * // will not work with plain functions, since the parameter names will be
1052 * // collapsed to a single letter identifier. To work around this, you can
1053 * // explicitly specify the names of the parameters your task function needs
1054 * // in an array, similar to Angular.js dependency injection.
1055 *
1056 * // This still has an advantage over plain `auto`, since the results a task
1057 * // depends on are still spread into arguments.
1058 * async.autoInject({
1059 * //...
1060 * write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) {
1061 * callback(null, 'filename');
1062 * }],
1063 * email_link: ['write_file', function(write_file, callback) {
1064 * callback(null, {'file':write_file, 'email':'user@example.com'});
1065 * }]
1066 * //...
1067 * }, function(err, results) {
1068 * console.log('err = ', err);
1069 * console.log('email_link = ', results.email_link);
1070 * });
1071 */
1072function autoInject(tasks, callback) {
1073 var newTasks = {};
1074
1075 Object.keys(tasks).forEach(key => {
1076 var taskFn = tasks[key];
1077 var params;
1078 var fnIsAsync = isAsync(taskFn);
1079 var hasNoDeps =
1080 (!fnIsAsync && taskFn.length === 1) ||
1081 (fnIsAsync && taskFn.length === 0);
1082
1083 if (Array.isArray(taskFn)) {
1084 params = [...taskFn];
1085 taskFn = params.pop();
1086
1087 newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn);
1088 } else if (hasNoDeps) {
1089 // no dependencies, use the function as-is
1090 newTasks[key] = taskFn;
1091 } else {
1092 params = parseParams(taskFn);
1093 if ((taskFn.length === 0 && !fnIsAsync) && params.length === 0) {
1094 throw new Error("autoInject task functions require explicit parameters.");
1095 }
1096
1097 // remove callback param
1098 if (!fnIsAsync) params.pop();
1099
1100 newTasks[key] = params.concat(newTask);
1101 }
1102
1103 function newTask(results, taskCb) {
1104 var newArgs = params.map(name => results[name]);
1105 newArgs.push(taskCb);
1106 wrapAsync(taskFn)(...newArgs);
1107 }
1108 });
1109
1110 return auto(newTasks, callback);
1111}
1112
1113// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation
1114// used for queues. This implementation assumes that the node provided by the user can be modified
1115// to adjust the next and last properties. We implement only the minimal functionality
1116// for queue support.
1117class DLL {
1118 constructor() {
1119 this.head = this.tail = null;
1120 this.length = 0;
1121 }
1122
1123 removeLink(node) {
1124 if (node.prev) node.prev.next = node.next;
1125 else this.head = node.next;
1126 if (node.next) node.next.prev = node.prev;
1127 else this.tail = node.prev;
1128
1129 node.prev = node.next = null;
1130 this.length -= 1;
1131 return node;
1132 }
1133
1134 empty () {
1135 while(this.head) this.shift();
1136 return this;
1137 }
1138
1139 insertAfter(node, newNode) {
1140 newNode.prev = node;
1141 newNode.next = node.next;
1142 if (node.next) node.next.prev = newNode;
1143 else this.tail = newNode;
1144 node.next = newNode;
1145 this.length += 1;
1146 }
1147
1148 insertBefore(node, newNode) {
1149 newNode.prev = node.prev;
1150 newNode.next = node;
1151 if (node.prev) node.prev.next = newNode;
1152 else this.head = newNode;
1153 node.prev = newNode;
1154 this.length += 1;
1155 }
1156
1157 unshift(node) {
1158 if (this.head) this.insertBefore(this.head, node);
1159 else setInitial(this, node);
1160 }
1161
1162 push(node) {
1163 if (this.tail) this.insertAfter(this.tail, node);
1164 else setInitial(this, node);
1165 }
1166
1167 shift() {
1168 return this.head && this.removeLink(this.head);
1169 }
1170
1171 pop() {
1172 return this.tail && this.removeLink(this.tail);
1173 }
1174
1175 toArray() {
1176 return [...this]
1177 }
1178
1179 *[Symbol.iterator] () {
1180 var cur = this.head;
1181 while (cur) {
1182 yield cur.data;
1183 cur = cur.next;
1184 }
1185 }
1186
1187 remove (testFn) {
1188 var curr = this.head;
1189 while(curr) {
1190 var {next} = curr;
1191 if (testFn(curr)) {
1192 this.removeLink(curr);
1193 }
1194 curr = next;
1195 }
1196 return this;
1197 }
1198}
1199
1200function setInitial(dll, node) {
1201 dll.length = 1;
1202 dll.head = dll.tail = node;
1203}
1204
1205function queue(worker, concurrency, payload) {
1206 if (concurrency == null) {
1207 concurrency = 1;
1208 }
1209 else if(concurrency === 0) {
1210 throw new RangeError('Concurrency must not be zero');
1211 }
1212
1213 var _worker = wrapAsync(worker);
1214 var numRunning = 0;
1215 var workersList = [];
1216 const events = {
1217 error: [],
1218 drain: [],
1219 saturated: [],
1220 unsaturated: [],
1221 empty: []
1222 };
1223
1224 function on (event, handler) {
1225 events[event].push(handler);
1226 }
1227
1228 function once (event, handler) {
1229 const handleAndRemove = (...args) => {
1230 off(event, handleAndRemove);
1231 handler(...args);
1232 };
1233 events[event].push(handleAndRemove);
1234 }
1235
1236 function off (event, handler) {
1237 if (!event) return Object.keys(events).forEach(ev => events[ev] = [])
1238 if (!handler) return events[event] = []
1239 events[event] = events[event].filter(ev => ev !== handler);
1240 }
1241
1242 function trigger (event, ...args) {
1243 events[event].forEach(handler => handler(...args));
1244 }
1245
1246 var processingScheduled = false;
1247 function _insert(data, insertAtFront, rejectOnError, callback) {
1248 if (callback != null && typeof callback !== 'function') {
1249 throw new Error('task callback must be a function');
1250 }
1251 q.started = true;
1252
1253 var res, rej;
1254 function promiseCallback (err, ...args) {
1255 // we don't care about the error, let the global error handler
1256 // deal with it
1257 if (err) return rejectOnError ? rej(err) : res()
1258 if (args.length <= 1) return res(args[0])
1259 res(args);
1260 }
1261
1262 var item = {
1263 data,
1264 callback: rejectOnError ?
1265 promiseCallback :
1266 (callback || promiseCallback)
1267 };
1268
1269 if (insertAtFront) {
1270 q._tasks.unshift(item);
1271 } else {
1272 q._tasks.push(item);
1273 }
1274
1275 if (!processingScheduled) {
1276 processingScheduled = true;
1277 setImmediate$1(() => {
1278 processingScheduled = false;
1279 q.process();
1280 });
1281 }
1282
1283 if (rejectOnError || !callback) {
1284 return new Promise((resolve, reject) => {
1285 res = resolve;
1286 rej = reject;
1287 })
1288 }
1289 }
1290
1291 function _createCB(tasks) {
1292 return function (err, ...args) {
1293 numRunning -= 1;
1294
1295 for (var i = 0, l = tasks.length; i < l; i++) {
1296 var task = tasks[i];
1297
1298 var index = workersList.indexOf(task);
1299 if (index === 0) {
1300 workersList.shift();
1301 } else if (index > 0) {
1302 workersList.splice(index, 1);
1303 }
1304
1305 task.callback(err, ...args);
1306
1307 if (err != null) {
1308 trigger('error', err, task.data);
1309 }
1310 }
1311
1312 if (numRunning <= (q.concurrency - q.buffer) ) {
1313 trigger('unsaturated');
1314 }
1315
1316 if (q.idle()) {
1317 trigger('drain');
1318 }
1319 q.process();
1320 };
1321 }
1322
1323 function _maybeDrain(data) {
1324 if (data.length === 0 && q.idle()) {
1325 // call drain immediately if there are no tasks
1326 setImmediate$1(() => trigger('drain'));
1327 return true
1328 }
1329 return false
1330 }
1331
1332 const eventMethod = (name) => (handler) => {
1333 if (!handler) {
1334 return new Promise((resolve, reject) => {
1335 once(name, (err, data) => {
1336 if (err) return reject(err)
1337 resolve(data);
1338 });
1339 })
1340 }
1341 off(name);
1342 on(name, handler);
1343
1344 };
1345
1346 var isProcessing = false;
1347 var q = {
1348 _tasks: new DLL(),
1349 *[Symbol.iterator] () {
1350 yield* q._tasks[Symbol.iterator]();
1351 },
1352 concurrency,
1353 payload,
1354 buffer: concurrency / 4,
1355 started: false,
1356 paused: false,
1357 push (data, callback) {
1358 if (Array.isArray(data)) {
1359 if (_maybeDrain(data)) return
1360 return data.map(datum => _insert(datum, false, false, callback))
1361 }
1362 return _insert(data, false, false, callback);
1363 },
1364 pushAsync (data, callback) {
1365 if (Array.isArray(data)) {
1366 if (_maybeDrain(data)) return
1367 return data.map(datum => _insert(datum, false, true, callback))
1368 }
1369 return _insert(data, false, true, callback);
1370 },
1371 kill () {
1372 off();
1373 q._tasks.empty();
1374 },
1375 unshift (data, callback) {
1376 if (Array.isArray(data)) {
1377 if (_maybeDrain(data)) return
1378 return data.map(datum => _insert(datum, true, false, callback))
1379 }
1380 return _insert(data, true, false, callback);
1381 },
1382 unshiftAsync (data, callback) {
1383 if (Array.isArray(data)) {
1384 if (_maybeDrain(data)) return
1385 return data.map(datum => _insert(datum, true, true, callback))
1386 }
1387 return _insert(data, true, true, callback);
1388 },
1389 remove (testFn) {
1390 q._tasks.remove(testFn);
1391 },
1392 process () {
1393 // Avoid trying to start too many processing operations. This can occur
1394 // when callbacks resolve synchronously (#1267).
1395 if (isProcessing) {
1396 return;
1397 }
1398 isProcessing = true;
1399 while(!q.paused && numRunning < q.concurrency && q._tasks.length){
1400 var tasks = [], data = [];
1401 var l = q._tasks.length;
1402 if (q.payload) l = Math.min(l, q.payload);
1403 for (var i = 0; i < l; i++) {
1404 var node = q._tasks.shift();
1405 tasks.push(node);
1406 workersList.push(node);
1407 data.push(node.data);
1408 }
1409
1410 numRunning += 1;
1411
1412 if (q._tasks.length === 0) {
1413 trigger('empty');
1414 }
1415
1416 if (numRunning === q.concurrency) {
1417 trigger('saturated');
1418 }
1419
1420 var cb = onlyOnce(_createCB(tasks));
1421 _worker(data, cb);
1422 }
1423 isProcessing = false;
1424 },
1425 length () {
1426 return q._tasks.length;
1427 },
1428 running () {
1429 return numRunning;
1430 },
1431 workersList () {
1432 return workersList;
1433 },
1434 idle() {
1435 return q._tasks.length + numRunning === 0;
1436 },
1437 pause () {
1438 q.paused = true;
1439 },
1440 resume () {
1441 if (q.paused === false) { return; }
1442 q.paused = false;
1443 setImmediate$1(q.process);
1444 }
1445 };
1446 // define these as fixed properties, so people get useful errors when updating
1447 Object.defineProperties(q, {
1448 saturated: {
1449 writable: false,
1450 value: eventMethod('saturated')
1451 },
1452 unsaturated: {
1453 writable: false,
1454 value: eventMethod('unsaturated')
1455 },
1456 empty: {
1457 writable: false,
1458 value: eventMethod('empty')
1459 },
1460 drain: {
1461 writable: false,
1462 value: eventMethod('drain')
1463 },
1464 error: {
1465 writable: false,
1466 value: eventMethod('error')
1467 },
1468 });
1469 return q;
1470}
1471
1472/**
1473 * Creates a `cargo` object with the specified payload. Tasks added to the
1474 * cargo will be processed altogether (up to the `payload` limit). If the
1475 * `worker` is in progress, the task is queued until it becomes available. Once
1476 * the `worker` has completed some tasks, each callback of those tasks is
1477 * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
1478 * for how `cargo` and `queue` work.
1479 *
1480 * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
1481 * at a time, cargo passes an array of tasks to a single worker, repeating
1482 * when the worker is finished.
1483 *
1484 * @name cargo
1485 * @static
1486 * @memberOf module:ControlFlow
1487 * @method
1488 * @see [async.queue]{@link module:ControlFlow.queue}
1489 * @category Control Flow
1490 * @param {AsyncFunction} worker - An asynchronous function for processing an array
1491 * of queued tasks. Invoked with `(tasks, callback)`.
1492 * @param {number} [payload=Infinity] - An optional `integer` for determining
1493 * how many tasks should be processed per round; if omitted, the default is
1494 * unlimited.
1495 * @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can
1496 * attached as certain properties to listen for specific events during the
1497 * lifecycle of the cargo and inner queue.
1498 * @example
1499 *
1500 * // create a cargo object with payload 2
1501 * var cargo = async.cargo(function(tasks, callback) {
1502 * for (var i=0; i<tasks.length; i++) {
1503 * console.log('hello ' + tasks[i].name);
1504 * }
1505 * callback();
1506 * }, 2);
1507 *
1508 * // add some items
1509 * cargo.push({name: 'foo'}, function(err) {
1510 * console.log('finished processing foo');
1511 * });
1512 * cargo.push({name: 'bar'}, function(err) {
1513 * console.log('finished processing bar');
1514 * });
1515 * await cargo.push({name: 'baz'});
1516 * console.log('finished processing baz');
1517 */
1518function cargo(worker, payload) {
1519 return queue(worker, 1, payload);
1520}
1521
1522/**
1523 * Creates a `cargoQueue` object with the specified payload. Tasks added to the
1524 * cargoQueue will be processed together (up to the `payload` limit) in `concurrency` parallel workers.
1525 * If the all `workers` are in progress, the task is queued until one becomes available. Once
1526 * a `worker` has completed some tasks, each callback of those tasks is
1527 * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
1528 * for how `cargo` and `queue` work.
1529 *
1530 * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
1531 * at a time, and [`cargo`]{@link module:ControlFlow.cargo} passes an array of tasks to a single worker,
1532 * the cargoQueue passes an array of tasks to multiple parallel workers.
1533 *
1534 * @name cargoQueue
1535 * @static
1536 * @memberOf module:ControlFlow
1537 * @method
1538 * @see [async.queue]{@link module:ControlFlow.queue}
1539 * @see [async.cargo]{@link module:ControlFLow.cargo}
1540 * @category Control Flow
1541 * @param {AsyncFunction} worker - An asynchronous function for processing an array
1542 * of queued tasks. Invoked with `(tasks, callback)`.
1543 * @param {number} [concurrency=1] - An `integer` for determining how many
1544 * `worker` functions should be run in parallel. If omitted, the concurrency
1545 * defaults to `1`. If the concurrency is `0`, an error is thrown.
1546 * @param {number} [payload=Infinity] - An optional `integer` for determining
1547 * how many tasks should be processed per round; if omitted, the default is
1548 * unlimited.
1549 * @returns {module:ControlFlow.QueueObject} A cargoQueue object to manage the tasks. Callbacks can
1550 * attached as certain properties to listen for specific events during the
1551 * lifecycle of the cargoQueue and inner queue.
1552 * @example
1553 *
1554 * // create a cargoQueue object with payload 2 and concurrency 2
1555 * var cargoQueue = async.cargoQueue(function(tasks, callback) {
1556 * for (var i=0; i<tasks.length; i++) {
1557 * console.log('hello ' + tasks[i].name);
1558 * }
1559 * callback();
1560 * }, 2, 2);
1561 *
1562 * // add some items
1563 * cargoQueue.push({name: 'foo'}, function(err) {
1564 * console.log('finished processing foo');
1565 * });
1566 * cargoQueue.push({name: 'bar'}, function(err) {
1567 * console.log('finished processing bar');
1568 * });
1569 * cargoQueue.push({name: 'baz'}, function(err) {
1570 * console.log('finished processing baz');
1571 * });
1572 * cargoQueue.push({name: 'boo'}, function(err) {
1573 * console.log('finished processing boo');
1574 * });
1575 */
1576function cargo$1(worker, concurrency, payload) {
1577 return queue(worker, concurrency, payload);
1578}
1579
1580/**
1581 * Reduces `coll` into a single value using an async `iteratee` to return each
1582 * successive step. `memo` is the initial state of the reduction. This function
1583 * only operates in series.
1584 *
1585 * For performance reasons, it may make sense to split a call to this function
1586 * into a parallel map, and then use the normal `Array.prototype.reduce` on the
1587 * results. This function is for situations where each step in the reduction
1588 * needs to be async; if you can get the data before reducing it, then it's
1589 * probably a good idea to do so.
1590 *
1591 * @name reduce
1592 * @static
1593 * @memberOf module:Collections
1594 * @method
1595 * @alias inject
1596 * @alias foldl
1597 * @category Collection
1598 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
1599 * @param {*} memo - The initial state of the reduction.
1600 * @param {AsyncFunction} iteratee - A function applied to each item in the
1601 * array to produce the next step in the reduction.
1602 * The `iteratee` should complete with the next state of the reduction.
1603 * If the iteratee complete with an error, the reduction is stopped and the
1604 * main `callback` is immediately called with the error.
1605 * Invoked with (memo, item, callback).
1606 * @param {Function} [callback] - A callback which is called after all the
1607 * `iteratee` functions have finished. Result is the reduced value. Invoked with
1608 * (err, result).
1609 * @returns {Promise} a promise, if no callback is passed
1610 * @example
1611 *
1612 * async.reduce([1,2,3], 0, function(memo, item, callback) {
1613 * // pointless async:
1614 * process.nextTick(function() {
1615 * callback(null, memo + item)
1616 * });
1617 * }, function(err, result) {
1618 * // result is now equal to the last value of memo, which is 6
1619 * });
1620 */
1621function reduce(coll, memo, iteratee, callback) {
1622 callback = once(callback);
1623 var _iteratee = wrapAsync(iteratee);
1624 return eachOfSeries$1(coll, (x, i, iterCb) => {
1625 _iteratee(memo, x, (err, v) => {
1626 memo = v;
1627 iterCb(err);
1628 });
1629 }, err => callback(err, memo));
1630}
1631var reduce$1 = awaitify(reduce, 4);
1632
1633/**
1634 * Version of the compose function that is more natural to read. Each function
1635 * consumes the return value of the previous function. It is the equivalent of
1636 * [compose]{@link module:ControlFlow.compose} with the arguments reversed.
1637 *
1638 * Each function is executed with the `this` binding of the composed function.
1639 *
1640 * @name seq
1641 * @static
1642 * @memberOf module:ControlFlow
1643 * @method
1644 * @see [async.compose]{@link module:ControlFlow.compose}
1645 * @category Control Flow
1646 * @param {...AsyncFunction} functions - the asynchronous functions to compose
1647 * @returns {Function} a function that composes the `functions` in order
1648 * @example
1649 *
1650 * // Requires lodash (or underscore), express3 and dresende's orm2.
1651 * // Part of an app, that fetches cats of the logged user.
1652 * // This example uses `seq` function to avoid overnesting and error
1653 * // handling clutter.
1654 * app.get('/cats', function(request, response) {
1655 * var User = request.models.User;
1656 * async.seq(
1657 * _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data))
1658 * function(user, fn) {
1659 * user.getCats(fn); // 'getCats' has signature (callback(err, data))
1660 * }
1661 * )(req.session.user_id, function (err, cats) {
1662 * if (err) {
1663 * console.error(err);
1664 * response.json({ status: 'error', message: err.message });
1665 * } else {
1666 * response.json({ status: 'ok', message: 'Cats found', data: cats });
1667 * }
1668 * });
1669 * });
1670 */
1671function seq(...functions) {
1672 var _functions = functions.map(wrapAsync);
1673 return function (...args) {
1674 var that = this;
1675
1676 var cb = args[args.length - 1];
1677 if (typeof cb == 'function') {
1678 args.pop();
1679 } else {
1680 cb = promiseCallback();
1681 }
1682
1683 reduce$1(_functions, args, (newargs, fn, iterCb) => {
1684 fn.apply(that, newargs.concat((err, ...nextargs) => {
1685 iterCb(err, nextargs);
1686 }));
1687 },
1688 (err, results) => cb(err, ...results));
1689
1690 return cb[PROMISE_SYMBOL]
1691 };
1692}
1693
1694/**
1695 * Creates a function which is a composition of the passed asynchronous
1696 * functions. Each function consumes the return value of the function that
1697 * follows. Composing functions `f()`, `g()`, and `h()` would produce the result
1698 * of `f(g(h()))`, only this version uses callbacks to obtain the return values.
1699 *
1700 * If the last argument to the composed function is not a function, a promise
1701 * is returned when you call it.
1702 *
1703 * Each function is executed with the `this` binding of the composed function.
1704 *
1705 * @name compose
1706 * @static
1707 * @memberOf module:ControlFlow
1708 * @method
1709 * @category Control Flow
1710 * @param {...AsyncFunction} functions - the asynchronous functions to compose
1711 * @returns {Function} an asynchronous function that is the composed
1712 * asynchronous `functions`
1713 * @example
1714 *
1715 * function add1(n, callback) {
1716 * setTimeout(function () {
1717 * callback(null, n + 1);
1718 * }, 10);
1719 * }
1720 *
1721 * function mul3(n, callback) {
1722 * setTimeout(function () {
1723 * callback(null, n * 3);
1724 * }, 10);
1725 * }
1726 *
1727 * var add1mul3 = async.compose(mul3, add1);
1728 * add1mul3(4, function (err, result) {
1729 * // result now equals 15
1730 * });
1731 */
1732function compose(...args) {
1733 return seq(...args.reverse());
1734}
1735
1736/**
1737 * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time.
1738 *
1739 * @name mapLimit
1740 * @static
1741 * @memberOf module:Collections
1742 * @method
1743 * @see [async.map]{@link module:Collections.map}
1744 * @category Collection
1745 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
1746 * @param {number} limit - The maximum number of async operations at a time.
1747 * @param {AsyncFunction} iteratee - An async function to apply to each item in
1748 * `coll`.
1749 * The iteratee should complete with the transformed item.
1750 * Invoked with (item, callback).
1751 * @param {Function} [callback] - A callback which is called when all `iteratee`
1752 * functions have finished, or an error occurs. Results is an array of the
1753 * transformed items from the `coll`. Invoked with (err, results).
1754 * @returns {Promise} a promise, if no callback is passed
1755 */
1756function mapLimit (coll, limit, iteratee, callback) {
1757 return _asyncMap(eachOfLimit(limit), coll, iteratee, callback)
1758}
1759var mapLimit$1 = awaitify(mapLimit, 4);
1760
1761/**
1762 * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time.
1763 *
1764 * @name concatLimit
1765 * @static
1766 * @memberOf module:Collections
1767 * @method
1768 * @see [async.concat]{@link module:Collections.concat}
1769 * @category Collection
1770 * @alias flatMapLimit
1771 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
1772 * @param {number} limit - The maximum number of async operations at a time.
1773 * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
1774 * which should use an array as its result. Invoked with (item, callback).
1775 * @param {Function} [callback] - A callback which is called after all the
1776 * `iteratee` functions have finished, or an error occurs. Results is an array
1777 * containing the concatenated results of the `iteratee` function. Invoked with
1778 * (err, results).
1779 * @returns A Promise, if no callback is passed
1780 */
1781function concatLimit(coll, limit, iteratee, callback) {
1782 var _iteratee = wrapAsync(iteratee);
1783 return mapLimit$1(coll, limit, (val, iterCb) => {
1784 _iteratee(val, (err, ...args) => {
1785 if (err) return iterCb(err);
1786 return iterCb(err, args);
1787 });
1788 }, (err, mapResults) => {
1789 var result = [];
1790 for (var i = 0; i < mapResults.length; i++) {
1791 if (mapResults[i]) {
1792 result = result.concat(...mapResults[i]);
1793 }
1794 }
1795
1796 return callback(err, result);
1797 });
1798}
1799var concatLimit$1 = awaitify(concatLimit, 4);
1800
1801/**
1802 * Applies `iteratee` to each item in `coll`, concatenating the results. Returns
1803 * the concatenated list. The `iteratee`s are called in parallel, and the
1804 * results are concatenated as they return. The results array will be returned in
1805 * the original order of `coll` passed to the `iteratee` function.
1806 *
1807 * @name concat
1808 * @static
1809 * @memberOf module:Collections
1810 * @method
1811 * @category Collection
1812 * @alias flatMap
1813 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
1814 * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
1815 * which should use an array as its result. Invoked with (item, callback).
1816 * @param {Function} [callback] - A callback which is called after all the
1817 * `iteratee` functions have finished, or an error occurs. Results is an array
1818 * containing the concatenated results of the `iteratee` function. Invoked with
1819 * (err, results).
1820 * @returns A Promise, if no callback is passed
1821 * @example
1822 *
1823 * async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files) {
1824 * // files is now a list of filenames that exist in the 3 directories
1825 * });
1826 */
1827function concat(coll, iteratee, callback) {
1828 return concatLimit$1(coll, Infinity, iteratee, callback)
1829}
1830var concat$1 = awaitify(concat, 3);
1831
1832/**
1833 * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time.
1834 *
1835 * @name concatSeries
1836 * @static
1837 * @memberOf module:Collections
1838 * @method
1839 * @see [async.concat]{@link module:Collections.concat}
1840 * @category Collection
1841 * @alias flatMapSeries
1842 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
1843 * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`.
1844 * The iteratee should complete with an array an array of results.
1845 * Invoked with (item, callback).
1846 * @param {Function} [callback] - A callback which is called after all the
1847 * `iteratee` functions have finished, or an error occurs. Results is an array
1848 * containing the concatenated results of the `iteratee` function. Invoked with
1849 * (err, results).
1850 * @returns A Promise, if no callback is passed
1851 */
1852function concatSeries(coll, iteratee, callback) {
1853 return concatLimit$1(coll, 1, iteratee, callback)
1854}
1855var concatSeries$1 = awaitify(concatSeries, 3);
1856
1857/**
1858 * Returns a function that when called, calls-back with the values provided.
1859 * Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to
1860 * [`auto`]{@link module:ControlFlow.auto}.
1861 *
1862 * @name constant
1863 * @static
1864 * @memberOf module:Utils
1865 * @method
1866 * @category Util
1867 * @param {...*} arguments... - Any number of arguments to automatically invoke
1868 * callback with.
1869 * @returns {AsyncFunction} Returns a function that when invoked, automatically
1870 * invokes the callback with the previous given arguments.
1871 * @example
1872 *
1873 * async.waterfall([
1874 * async.constant(42),
1875 * function (value, next) {
1876 * // value === 42
1877 * },
1878 * //...
1879 * ], callback);
1880 *
1881 * async.waterfall([
1882 * async.constant(filename, "utf8"),
1883 * fs.readFile,
1884 * function (fileData, next) {
1885 * //...
1886 * }
1887 * //...
1888 * ], callback);
1889 *
1890 * async.auto({
1891 * hostname: async.constant("https://server.net/"),
1892 * port: findFreePort,
1893 * launchServer: ["hostname", "port", function (options, cb) {
1894 * startServer(options, cb);
1895 * }],
1896 * //...
1897 * }, callback);
1898 */
1899function constant(...args) {
1900 return function (...ignoredArgs/*, callback*/) {
1901 var callback = ignoredArgs.pop();
1902 return callback(null, ...args);
1903 };
1904}
1905
1906function _createTester(check, getResult) {
1907 return (eachfn, arr, _iteratee, cb) => {
1908 var testPassed = false;
1909 var testResult;
1910 const iteratee = wrapAsync(_iteratee);
1911 eachfn(arr, (value, _, callback) => {
1912 iteratee(value, (err, result) => {
1913 if (err || err === false) return callback(err);
1914
1915 if (check(result) && !testResult) {
1916 testPassed = true;
1917 testResult = getResult(true, value);
1918 return callback(null, breakLoop);
1919 }
1920 callback();
1921 });
1922 }, err => {
1923 if (err) return cb(err);
1924 cb(null, testPassed ? testResult : getResult(false));
1925 });
1926 };
1927}
1928
1929/**
1930 * Returns the first value in `coll` that passes an async truth test. The
1931 * `iteratee` is applied in parallel, meaning the first iteratee to return
1932 * `true` will fire the detect `callback` with that result. That means the
1933 * result might not be the first item in the original `coll` (in terms of order)
1934 * that passes the test.
1935
1936 * If order within the original `coll` is important, then look at
1937 * [`detectSeries`]{@link module:Collections.detectSeries}.
1938 *
1939 * @name detect
1940 * @static
1941 * @memberOf module:Collections
1942 * @method
1943 * @alias find
1944 * @category Collections
1945 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
1946 * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
1947 * The iteratee must complete with a boolean value as its result.
1948 * Invoked with (item, callback).
1949 * @param {Function} [callback] - A callback which is called as soon as any
1950 * iteratee returns `true`, or after all the `iteratee` functions have finished.
1951 * Result will be the first item in the array that passes the truth test
1952 * (iteratee) or the value `undefined` if none passed. Invoked with
1953 * (err, result).
1954 * @returns A Promise, if no callback is passed
1955 * @example
1956 *
1957 * async.detect(['file1','file2','file3'], function(filePath, callback) {
1958 * fs.access(filePath, function(err) {
1959 * callback(null, !err)
1960 * });
1961 * }, function(err, result) {
1962 * // result now equals the first file in the list that exists
1963 * });
1964 */
1965function detect(coll, iteratee, callback) {
1966 return _createTester(bool => bool, (res, item) => item)(eachOf$1, coll, iteratee, callback)
1967}
1968var detect$1 = awaitify(detect, 3);
1969
1970/**
1971 * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a
1972 * time.
1973 *
1974 * @name detectLimit
1975 * @static
1976 * @memberOf module:Collections
1977 * @method
1978 * @see [async.detect]{@link module:Collections.detect}
1979 * @alias findLimit
1980 * @category Collections
1981 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
1982 * @param {number} limit - The maximum number of async operations at a time.
1983 * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
1984 * The iteratee must complete with a boolean value as its result.
1985 * Invoked with (item, callback).
1986 * @param {Function} [callback] - A callback which is called as soon as any
1987 * iteratee returns `true`, or after all the `iteratee` functions have finished.
1988 * Result will be the first item in the array that passes the truth test
1989 * (iteratee) or the value `undefined` if none passed. Invoked with
1990 * (err, result).
1991 * @returns a Promise if no callback is passed
1992 */
1993function detectLimit(coll, limit, iteratee, callback) {
1994 return _createTester(bool => bool, (res, item) => item)(eachOfLimit(limit), coll, iteratee, callback)
1995}
1996var detectLimit$1 = awaitify(detectLimit, 4);
1997
1998/**
1999 * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time.
2000 *
2001 * @name detectSeries
2002 * @static
2003 * @memberOf module:Collections
2004 * @method
2005 * @see [async.detect]{@link module:Collections.detect}
2006 * @alias findSeries
2007 * @category Collections
2008 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2009 * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
2010 * The iteratee must complete with a boolean value as its result.
2011 * Invoked with (item, callback).
2012 * @param {Function} [callback] - A callback which is called as soon as any
2013 * iteratee returns `true`, or after all the `iteratee` functions have finished.
2014 * Result will be the first item in the array that passes the truth test
2015 * (iteratee) or the value `undefined` if none passed. Invoked with
2016 * (err, result).
2017 * @returns a Promise if no callback is passed
2018 */
2019function detectSeries(coll, iteratee, callback) {
2020 return _createTester(bool => bool, (res, item) => item)(eachOfLimit(1), coll, iteratee, callback)
2021}
2022
2023var detectSeries$1 = awaitify(detectSeries, 3);
2024
2025function consoleFunc(name) {
2026 return (fn, ...args) => wrapAsync(fn)(...args, (err, ...resultArgs) => {
2027 if (typeof console === 'object') {
2028 if (err) {
2029 if (console.error) {
2030 console.error(err);
2031 }
2032 } else if (console[name]) {
2033 resultArgs.forEach(x => console[name](x));
2034 }
2035 }
2036 })
2037}
2038
2039/**
2040 * Logs the result of an [`async` function]{@link AsyncFunction} to the
2041 * `console` using `console.dir` to display the properties of the resulting object.
2042 * Only works in Node.js or in browsers that support `console.dir` and
2043 * `console.error` (such as FF and Chrome).
2044 * If multiple arguments are returned from the async function,
2045 * `console.dir` is called on each argument in order.
2046 *
2047 * @name dir
2048 * @static
2049 * @memberOf module:Utils
2050 * @method
2051 * @category Util
2052 * @param {AsyncFunction} function - The function you want to eventually apply
2053 * all arguments to.
2054 * @param {...*} arguments... - Any number of arguments to apply to the function.
2055 * @example
2056 *
2057 * // in a module
2058 * var hello = function(name, callback) {
2059 * setTimeout(function() {
2060 * callback(null, {hello: name});
2061 * }, 1000);
2062 * };
2063 *
2064 * // in the node repl
2065 * node> async.dir(hello, 'world');
2066 * {hello: 'world'}
2067 */
2068var dir = consoleFunc('dir');
2069
2070/**
2071 * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in
2072 * the order of operations, the arguments `test` and `iteratee` are switched.
2073 *
2074 * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
2075 *
2076 * @name doWhilst
2077 * @static
2078 * @memberOf module:ControlFlow
2079 * @method
2080 * @see [async.whilst]{@link module:ControlFlow.whilst}
2081 * @category Control Flow
2082 * @param {AsyncFunction} iteratee - A function which is called each time `test`
2083 * passes. Invoked with (callback).
2084 * @param {AsyncFunction} test - asynchronous truth test to perform after each
2085 * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
2086 * non-error args from the previous callback of `iteratee`.
2087 * @param {Function} [callback] - A callback which is called after the test
2088 * function has failed and repeated execution of `iteratee` has stopped.
2089 * `callback` will be passed an error and any arguments passed to the final
2090 * `iteratee`'s callback. Invoked with (err, [results]);
2091 * @returns {Promise} a promise, if no callback is passed
2092 */
2093function doWhilst(iteratee, test, callback) {
2094 callback = onlyOnce(callback);
2095 var _fn = wrapAsync(iteratee);
2096 var _test = wrapAsync(test);
2097 var results;
2098
2099 function next(err, ...args) {
2100 if (err) return callback(err);
2101 if (err === false) return;
2102 results = args;
2103 _test(...args, check);
2104 }
2105
2106 function check(err, truth) {
2107 if (err) return callback(err);
2108 if (err === false) return;
2109 if (!truth) return callback(null, ...results);
2110 _fn(next);
2111 }
2112
2113 return check(null, true);
2114}
2115
2116var doWhilst$1 = awaitify(doWhilst, 3);
2117
2118/**
2119 * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the
2120 * argument ordering differs from `until`.
2121 *
2122 * @name doUntil
2123 * @static
2124 * @memberOf module:ControlFlow
2125 * @method
2126 * @see [async.doWhilst]{@link module:ControlFlow.doWhilst}
2127 * @category Control Flow
2128 * @param {AsyncFunction} iteratee - An async function which is called each time
2129 * `test` fails. Invoked with (callback).
2130 * @param {AsyncFunction} test - asynchronous truth test to perform after each
2131 * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
2132 * non-error args from the previous callback of `iteratee`
2133 * @param {Function} [callback] - A callback which is called after the test
2134 * function has passed and repeated execution of `iteratee` has stopped. `callback`
2135 * will be passed an error and any arguments passed to the final `iteratee`'s
2136 * callback. Invoked with (err, [results]);
2137 * @returns {Promise} a promise, if no callback is passed
2138 */
2139function doUntil(iteratee, test, callback) {
2140 const _test = wrapAsync(test);
2141 return doWhilst$1(iteratee, (...args) => {
2142 const cb = args.pop();
2143 _test(...args, (err, truth) => cb (err, !truth));
2144 }, callback);
2145}
2146
2147function _withoutIndex(iteratee) {
2148 return (value, index, callback) => iteratee(value, callback);
2149}
2150
2151/**
2152 * Applies the function `iteratee` to each item in `coll`, in parallel.
2153 * The `iteratee` is called with an item from the list, and a callback for when
2154 * it has finished. If the `iteratee` passes an error to its `callback`, the
2155 * main `callback` (for the `each` function) is immediately called with the
2156 * error.
2157 *
2158 * Note, that since this function applies `iteratee` to each item in parallel,
2159 * there is no guarantee that the iteratee functions will complete in order.
2160 *
2161 * @name each
2162 * @static
2163 * @memberOf module:Collections
2164 * @method
2165 * @alias forEach
2166 * @category Collection
2167 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2168 * @param {AsyncFunction} iteratee - An async function to apply to
2169 * each item in `coll`. Invoked with (item, callback).
2170 * The array index is not passed to the iteratee.
2171 * If you need the index, use `eachOf`.
2172 * @param {Function} [callback] - A callback which is called when all
2173 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
2174 * @returns {Promise} a promise, if a callback is omitted
2175 * @example
2176 *
2177 * // assuming openFiles is an array of file names and saveFile is a function
2178 * // to save the modified contents of that file:
2179 *
2180 * async.each(openFiles, saveFile, function(err){
2181 * // if any of the saves produced an error, err would equal that error
2182 * });
2183 *
2184 * // assuming openFiles is an array of file names
2185 * async.each(openFiles, function(file, callback) {
2186 *
2187 * // Perform operation on file here.
2188 * console.log('Processing file ' + file);
2189 *
2190 * if( file.length > 32 ) {
2191 * console.log('This file name is too long');
2192 * callback('File name too long');
2193 * } else {
2194 * // Do work to process file here
2195 * console.log('File processed');
2196 * callback();
2197 * }
2198 * }, function(err) {
2199 * // if any of the file processing produced an error, err would equal that error
2200 * if( err ) {
2201 * // One of the iterations produced an error.
2202 * // All processing will now stop.
2203 * console.log('A file failed to process');
2204 * } else {
2205 * console.log('All files have been processed successfully');
2206 * }
2207 * });
2208 */
2209function eachLimit(coll, iteratee, callback) {
2210 return eachOf$1(coll, _withoutIndex(wrapAsync(iteratee)), callback);
2211}
2212
2213var each = awaitify(eachLimit, 3);
2214
2215/**
2216 * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time.
2217 *
2218 * @name eachLimit
2219 * @static
2220 * @memberOf module:Collections
2221 * @method
2222 * @see [async.each]{@link module:Collections.each}
2223 * @alias forEachLimit
2224 * @category Collection
2225 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2226 * @param {number} limit - The maximum number of async operations at a time.
2227 * @param {AsyncFunction} iteratee - An async function to apply to each item in
2228 * `coll`.
2229 * The array index is not passed to the iteratee.
2230 * If you need the index, use `eachOfLimit`.
2231 * Invoked with (item, callback).
2232 * @param {Function} [callback] - A callback which is called when all
2233 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
2234 * @returns {Promise} a promise, if a callback is omitted
2235 */
2236function eachLimit$1(coll, limit, iteratee, callback) {
2237 return eachOfLimit(limit)(coll, _withoutIndex(wrapAsync(iteratee)), callback);
2238}
2239var eachLimit$2 = awaitify(eachLimit$1, 4);
2240
2241/**
2242 * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time.
2243 *
2244 * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item
2245 * in series and therefore the iteratee functions will complete in order.
2246
2247 * @name eachSeries
2248 * @static
2249 * @memberOf module:Collections
2250 * @method
2251 * @see [async.each]{@link module:Collections.each}
2252 * @alias forEachSeries
2253 * @category Collection
2254 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2255 * @param {AsyncFunction} iteratee - An async function to apply to each
2256 * item in `coll`.
2257 * The array index is not passed to the iteratee.
2258 * If you need the index, use `eachOfSeries`.
2259 * Invoked with (item, callback).
2260 * @param {Function} [callback] - A callback which is called when all
2261 * `iteratee` functions have finished, or an error occurs. Invoked with (err).
2262 * @returns {Promise} a promise, if a callback is omitted
2263 */
2264function eachSeries(coll, iteratee, callback) {
2265 return eachLimit$2(coll, 1, iteratee, callback)
2266}
2267var eachSeries$1 = awaitify(eachSeries, 3);
2268
2269/**
2270 * Wrap an async function and ensure it calls its callback on a later tick of
2271 * the event loop. If the function already calls its callback on a next tick,
2272 * no extra deferral is added. This is useful for preventing stack overflows
2273 * (`RangeError: Maximum call stack size exceeded`) and generally keeping
2274 * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony)
2275 * contained. ES2017 `async` functions are returned as-is -- they are immune
2276 * to Zalgo's corrupting influences, as they always resolve on a later tick.
2277 *
2278 * @name ensureAsync
2279 * @static
2280 * @memberOf module:Utils
2281 * @method
2282 * @category Util
2283 * @param {AsyncFunction} fn - an async function, one that expects a node-style
2284 * callback as its last argument.
2285 * @returns {AsyncFunction} Returns a wrapped function with the exact same call
2286 * signature as the function passed in.
2287 * @example
2288 *
2289 * function sometimesAsync(arg, callback) {
2290 * if (cache[arg]) {
2291 * return callback(null, cache[arg]); // this would be synchronous!!
2292 * } else {
2293 * doSomeIO(arg, callback); // this IO would be asynchronous
2294 * }
2295 * }
2296 *
2297 * // this has a risk of stack overflows if many results are cached in a row
2298 * async.mapSeries(args, sometimesAsync, done);
2299 *
2300 * // this will defer sometimesAsync's callback if necessary,
2301 * // preventing stack overflows
2302 * async.mapSeries(args, async.ensureAsync(sometimesAsync), done);
2303 */
2304function ensureAsync(fn) {
2305 if (isAsync(fn)) return fn;
2306 return function (...args/*, callback*/) {
2307 var callback = args.pop();
2308 var sync = true;
2309 args.push((...innerArgs) => {
2310 if (sync) {
2311 setImmediate$1(() => callback(...innerArgs));
2312 } else {
2313 callback(...innerArgs);
2314 }
2315 });
2316 fn.apply(this, args);
2317 sync = false;
2318 };
2319}
2320
2321/**
2322 * Returns `true` if every element in `coll` satisfies an async test. If any
2323 * iteratee call returns `false`, the main `callback` is immediately called.
2324 *
2325 * @name every
2326 * @static
2327 * @memberOf module:Collections
2328 * @method
2329 * @alias all
2330 * @category Collection
2331 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2332 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
2333 * in the collection in parallel.
2334 * The iteratee must complete with a boolean result value.
2335 * Invoked with (item, callback).
2336 * @param {Function} [callback] - A callback which is called after all the
2337 * `iteratee` functions have finished. Result will be either `true` or `false`
2338 * depending on the values of the async tests. Invoked with (err, result).
2339 * @returns {Promise} a promise, if no callback provided
2340 * @example
2341 *
2342 * async.every(['file1','file2','file3'], function(filePath, callback) {
2343 * fs.access(filePath, function(err) {
2344 * callback(null, !err)
2345 * });
2346 * }, function(err, result) {
2347 * // if result is true then every file exists
2348 * });
2349 */
2350function every(coll, iteratee, callback) {
2351 return _createTester(bool => !bool, res => !res)(eachOf$1, coll, iteratee, callback)
2352}
2353var every$1 = awaitify(every, 3);
2354
2355/**
2356 * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time.
2357 *
2358 * @name everyLimit
2359 * @static
2360 * @memberOf module:Collections
2361 * @method
2362 * @see [async.every]{@link module:Collections.every}
2363 * @alias allLimit
2364 * @category Collection
2365 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2366 * @param {number} limit - The maximum number of async operations at a time.
2367 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
2368 * in the collection in parallel.
2369 * The iteratee must complete with a boolean result value.
2370 * Invoked with (item, callback).
2371 * @param {Function} [callback] - A callback which is called after all the
2372 * `iteratee` functions have finished. Result will be either `true` or `false`
2373 * depending on the values of the async tests. Invoked with (err, result).
2374 * @returns {Promise} a promise, if no callback provided
2375 */
2376function everyLimit(coll, limit, iteratee, callback) {
2377 return _createTester(bool => !bool, res => !res)(eachOfLimit(limit), coll, iteratee, callback)
2378}
2379var everyLimit$1 = awaitify(everyLimit, 4);
2380
2381/**
2382 * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time.
2383 *
2384 * @name everySeries
2385 * @static
2386 * @memberOf module:Collections
2387 * @method
2388 * @see [async.every]{@link module:Collections.every}
2389 * @alias allSeries
2390 * @category Collection
2391 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2392 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
2393 * in the collection in series.
2394 * The iteratee must complete with a boolean result value.
2395 * Invoked with (item, callback).
2396 * @param {Function} [callback] - A callback which is called after all the
2397 * `iteratee` functions have finished. Result will be either `true` or `false`
2398 * depending on the values of the async tests. Invoked with (err, result).
2399 * @returns {Promise} a promise, if no callback provided
2400 */
2401function everySeries(coll, iteratee, callback) {
2402 return _createTester(bool => !bool, res => !res)(eachOfSeries$1, coll, iteratee, callback)
2403}
2404var everySeries$1 = awaitify(everySeries, 3);
2405
2406function filterArray(eachfn, arr, iteratee, callback) {
2407 var truthValues = new Array(arr.length);
2408 eachfn(arr, (x, index, iterCb) => {
2409 iteratee(x, (err, v) => {
2410 truthValues[index] = !!v;
2411 iterCb(err);
2412 });
2413 }, err => {
2414 if (err) return callback(err);
2415 var results = [];
2416 for (var i = 0; i < arr.length; i++) {
2417 if (truthValues[i]) results.push(arr[i]);
2418 }
2419 callback(null, results);
2420 });
2421}
2422
2423function filterGeneric(eachfn, coll, iteratee, callback) {
2424 var results = [];
2425 eachfn(coll, (x, index, iterCb) => {
2426 iteratee(x, (err, v) => {
2427 if (err) return iterCb(err);
2428 if (v) {
2429 results.push({index, value: x});
2430 }
2431 iterCb(err);
2432 });
2433 }, err => {
2434 if (err) return callback(err);
2435 callback(null, results
2436 .sort((a, b) => a.index - b.index)
2437 .map(v => v.value));
2438 });
2439}
2440
2441function _filter(eachfn, coll, iteratee, callback) {
2442 var filter = isArrayLike(coll) ? filterArray : filterGeneric;
2443 return filter(eachfn, coll, wrapAsync(iteratee), callback);
2444}
2445
2446/**
2447 * Returns a new array of all the values in `coll` which pass an async truth
2448 * test. This operation is performed in parallel, but the results array will be
2449 * in the same order as the original.
2450 *
2451 * @name filter
2452 * @static
2453 * @memberOf module:Collections
2454 * @method
2455 * @alias select
2456 * @category Collection
2457 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2458 * @param {Function} iteratee - A truth test to apply to each item in `coll`.
2459 * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
2460 * with a boolean argument once it has completed. Invoked with (item, callback).
2461 * @param {Function} [callback] - A callback which is called after all the
2462 * `iteratee` functions have finished. Invoked with (err, results).
2463 * @returns {Promise} a promise, if no callback provided
2464 * @example
2465 *
2466 * async.filter(['file1','file2','file3'], function(filePath, callback) {
2467 * fs.access(filePath, function(err) {
2468 * callback(null, !err)
2469 * });
2470 * }, function(err, results) {
2471 * // results now equals an array of the existing files
2472 * });
2473 */
2474function filter (coll, iteratee, callback) {
2475 return _filter(eachOf$1, coll, iteratee, callback)
2476}
2477var filter$1 = awaitify(filter, 3);
2478
2479/**
2480 * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a
2481 * time.
2482 *
2483 * @name filterLimit
2484 * @static
2485 * @memberOf module:Collections
2486 * @method
2487 * @see [async.filter]{@link module:Collections.filter}
2488 * @alias selectLimit
2489 * @category Collection
2490 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2491 * @param {number} limit - The maximum number of async operations at a time.
2492 * @param {Function} iteratee - A truth test to apply to each item in `coll`.
2493 * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
2494 * with a boolean argument once it has completed. Invoked with (item, callback).
2495 * @param {Function} [callback] - A callback which is called after all the
2496 * `iteratee` functions have finished. Invoked with (err, results).
2497 * @returns {Promise} a promise, if no callback provided
2498 */
2499function filterLimit (coll, limit, iteratee, callback) {
2500 return _filter(eachOfLimit(limit), coll, iteratee, callback)
2501}
2502var filterLimit$1 = awaitify(filterLimit, 4);
2503
2504/**
2505 * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time.
2506 *
2507 * @name filterSeries
2508 * @static
2509 * @memberOf module:Collections
2510 * @method
2511 * @see [async.filter]{@link module:Collections.filter}
2512 * @alias selectSeries
2513 * @category Collection
2514 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2515 * @param {Function} iteratee - A truth test to apply to each item in `coll`.
2516 * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
2517 * with a boolean argument once it has completed. Invoked with (item, callback).
2518 * @param {Function} [callback] - A callback which is called after all the
2519 * `iteratee` functions have finished. Invoked with (err, results)
2520 * @returns {Promise} a promise, if no callback provided
2521 */
2522function filterSeries (coll, iteratee, callback) {
2523 return _filter(eachOfSeries$1, coll, iteratee, callback)
2524}
2525var filterSeries$1 = awaitify(filterSeries, 3);
2526
2527/**
2528 * Calls the asynchronous function `fn` with a callback parameter that allows it
2529 * to call itself again, in series, indefinitely.
2530
2531 * If an error is passed to the callback then `errback` is called with the
2532 * error, and execution stops, otherwise it will never be called.
2533 *
2534 * @name forever
2535 * @static
2536 * @memberOf module:ControlFlow
2537 * @method
2538 * @category Control Flow
2539 * @param {AsyncFunction} fn - an async function to call repeatedly.
2540 * Invoked with (next).
2541 * @param {Function} [errback] - when `fn` passes an error to it's callback,
2542 * this function will be called, and execution stops. Invoked with (err).
2543 * @returns {Promise} a promise that rejects if an error occurs and an errback
2544 * is not passed
2545 * @example
2546 *
2547 * async.forever(
2548 * function(next) {
2549 * // next is suitable for passing to things that need a callback(err [, whatever]);
2550 * // it will result in this function being called again.
2551 * },
2552 * function(err) {
2553 * // if next is called with a value in its first parameter, it will appear
2554 * // in here as 'err', and execution will stop.
2555 * }
2556 * );
2557 */
2558function forever(fn, errback) {
2559 var done = onlyOnce(errback);
2560 var task = wrapAsync(ensureAsync(fn));
2561
2562 function next(err) {
2563 if (err) return done(err);
2564 if (err === false) return;
2565 task(next);
2566 }
2567 return next();
2568}
2569var forever$1 = awaitify(forever, 2);
2570
2571/**
2572 * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time.
2573 *
2574 * @name groupByLimit
2575 * @static
2576 * @memberOf module:Collections
2577 * @method
2578 * @see [async.groupBy]{@link module:Collections.groupBy}
2579 * @category Collection
2580 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2581 * @param {number} limit - The maximum number of async operations at a time.
2582 * @param {AsyncFunction} iteratee - An async function to apply to each item in
2583 * `coll`.
2584 * The iteratee should complete with a `key` to group the value under.
2585 * Invoked with (value, callback).
2586 * @param {Function} [callback] - A callback which is called when all `iteratee`
2587 * functions have finished, or an error occurs. Result is an `Object` whoses
2588 * properties are arrays of values which returned the corresponding key.
2589 * @returns {Promise} a promise, if no callback is passed
2590 */
2591function groupByLimit(coll, limit, iteratee, callback) {
2592 var _iteratee = wrapAsync(iteratee);
2593 return mapLimit$1(coll, limit, (val, iterCb) => {
2594 _iteratee(val, (err, key) => {
2595 if (err) return iterCb(err);
2596 return iterCb(err, {key, val});
2597 });
2598 }, (err, mapResults) => {
2599 var result = {};
2600 // from MDN, handle object having an `hasOwnProperty` prop
2601 var {hasOwnProperty} = Object.prototype;
2602
2603 for (var i = 0; i < mapResults.length; i++) {
2604 if (mapResults[i]) {
2605 var {key} = mapResults[i];
2606 var {val} = mapResults[i];
2607
2608 if (hasOwnProperty.call(result, key)) {
2609 result[key].push(val);
2610 } else {
2611 result[key] = [val];
2612 }
2613 }
2614 }
2615
2616 return callback(err, result);
2617 });
2618}
2619
2620var groupByLimit$1 = awaitify(groupByLimit, 4);
2621
2622/**
2623 * Returns a new object, where each value corresponds to an array of items, from
2624 * `coll`, that returned the corresponding key. That is, the keys of the object
2625 * correspond to the values passed to the `iteratee` callback.
2626 *
2627 * Note: Since this function applies the `iteratee` to each item in parallel,
2628 * there is no guarantee that the `iteratee` functions will complete in order.
2629 * However, the values for each key in the `result` will be in the same order as
2630 * the original `coll`. For Objects, the values will roughly be in the order of
2631 * the original Objects' keys (but this can vary across JavaScript engines).
2632 *
2633 * @name groupBy
2634 * @static
2635 * @memberOf module:Collections
2636 * @method
2637 * @category Collection
2638 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2639 * @param {AsyncFunction} iteratee - An async function to apply to each item in
2640 * `coll`.
2641 * The iteratee should complete with a `key` to group the value under.
2642 * Invoked with (value, callback).
2643 * @param {Function} [callback] - A callback which is called when all `iteratee`
2644 * functions have finished, or an error occurs. Result is an `Object` whoses
2645 * properties are arrays of values which returned the corresponding key.
2646 * @returns {Promise} a promise, if no callback is passed
2647 * @example
2648 *
2649 * async.groupBy(['userId1', 'userId2', 'userId3'], function(userId, callback) {
2650 * db.findById(userId, function(err, user) {
2651 * if (err) return callback(err);
2652 * return callback(null, user.age);
2653 * });
2654 * }, function(err, result) {
2655 * // result is object containing the userIds grouped by age
2656 * // e.g. { 30: ['userId1', 'userId3'], 42: ['userId2']};
2657 * });
2658 */
2659function groupBy (coll, iteratee, callback) {
2660 return groupByLimit$1(coll, Infinity, iteratee, callback)
2661}
2662
2663/**
2664 * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time.
2665 *
2666 * @name groupBySeries
2667 * @static
2668 * @memberOf module:Collections
2669 * @method
2670 * @see [async.groupBy]{@link module:Collections.groupBy}
2671 * @category Collection
2672 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
2673 * @param {AsyncFunction} iteratee - An async function to apply to each item in
2674 * `coll`.
2675 * The iteratee should complete with a `key` to group the value under.
2676 * Invoked with (value, callback).
2677 * @param {Function} [callback] - A callback which is called when all `iteratee`
2678 * functions have finished, or an error occurs. Result is an `Object` whoses
2679 * properties are arrays of values which returned the corresponding key.
2680 * @returns {Promise} a promise, if no callback is passed
2681 */
2682function groupBySeries (coll, iteratee, callback) {
2683 return groupByLimit$1(coll, 1, iteratee, callback)
2684}
2685
2686/**
2687 * Logs the result of an `async` function to the `console`. Only works in
2688 * Node.js or in browsers that support `console.log` and `console.error` (such
2689 * as FF and Chrome). If multiple arguments are returned from the async
2690 * function, `console.log` is called on each argument in order.
2691 *
2692 * @name log
2693 * @static
2694 * @memberOf module:Utils
2695 * @method
2696 * @category Util
2697 * @param {AsyncFunction} function - The function you want to eventually apply
2698 * all arguments to.
2699 * @param {...*} arguments... - Any number of arguments to apply to the function.
2700 * @example
2701 *
2702 * // in a module
2703 * var hello = function(name, callback) {
2704 * setTimeout(function() {
2705 * callback(null, 'hello ' + name);
2706 * }, 1000);
2707 * };
2708 *
2709 * // in the node repl
2710 * node> async.log(hello, 'world');
2711 * 'hello world'
2712 */
2713var log = consoleFunc('log');
2714
2715/**
2716 * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a
2717 * time.
2718 *
2719 * @name mapValuesLimit
2720 * @static
2721 * @memberOf module:Collections
2722 * @method
2723 * @see [async.mapValues]{@link module:Collections.mapValues}
2724 * @category Collection
2725 * @param {Object} obj - A collection to iterate over.
2726 * @param {number} limit - The maximum number of async operations at a time.
2727 * @param {AsyncFunction} iteratee - A function to apply to each value and key
2728 * in `coll`.
2729 * The iteratee should complete with the transformed value as its result.
2730 * Invoked with (value, key, callback).
2731 * @param {Function} [callback] - A callback which is called when all `iteratee`
2732 * functions have finished, or an error occurs. `result` is a new object consisting
2733 * of each key from `obj`, with each transformed value on the right-hand side.
2734 * Invoked with (err, result).
2735 * @returns {Promise} a promise, if no callback is passed
2736 */
2737function mapValuesLimit(obj, limit, iteratee, callback) {
2738 callback = once(callback);
2739 var newObj = {};
2740 var _iteratee = wrapAsync(iteratee);
2741 return eachOfLimit(limit)(obj, (val, key, next) => {
2742 _iteratee(val, key, (err, result) => {
2743 if (err) return next(err);
2744 newObj[key] = result;
2745 next(err);
2746 });
2747 }, err => callback(err, newObj));
2748}
2749
2750var mapValuesLimit$1 = awaitify(mapValuesLimit, 4);
2751
2752/**
2753 * A relative of [`map`]{@link module:Collections.map}, designed for use with objects.
2754 *
2755 * Produces a new Object by mapping each value of `obj` through the `iteratee`
2756 * function. The `iteratee` is called each `value` and `key` from `obj` and a
2757 * callback for when it has finished processing. Each of these callbacks takes
2758 * two arguments: an `error`, and the transformed item from `obj`. If `iteratee`
2759 * passes an error to its callback, the main `callback` (for the `mapValues`
2760 * function) is immediately called with the error.
2761 *
2762 * Note, the order of the keys in the result is not guaranteed. The keys will
2763 * be roughly in the order they complete, (but this is very engine-specific)
2764 *
2765 * @name mapValues
2766 * @static
2767 * @memberOf module:Collections
2768 * @method
2769 * @category Collection
2770 * @param {Object} obj - A collection to iterate over.
2771 * @param {AsyncFunction} iteratee - A function to apply to each value and key
2772 * in `coll`.
2773 * The iteratee should complete with the transformed value as its result.
2774 * Invoked with (value, key, callback).
2775 * @param {Function} [callback] - A callback which is called when all `iteratee`
2776 * functions have finished, or an error occurs. `result` is a new object consisting
2777 * of each key from `obj`, with each transformed value on the right-hand side.
2778 * Invoked with (err, result).
2779 * @returns {Promise} a promise, if no callback is passed
2780 * @example
2781 *
2782 * async.mapValues({
2783 * f1: 'file1',
2784 * f2: 'file2',
2785 * f3: 'file3'
2786 * }, function (file, key, callback) {
2787 * fs.stat(file, callback);
2788 * }, function(err, result) {
2789 * // result is now a map of stats for each file, e.g.
2790 * // {
2791 * // f1: [stats for file1],
2792 * // f2: [stats for file2],
2793 * // f3: [stats for file3]
2794 * // }
2795 * });
2796 */
2797function mapValues(obj, iteratee, callback) {
2798 return mapValuesLimit$1(obj, Infinity, iteratee, callback)
2799}
2800
2801/**
2802 * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time.
2803 *
2804 * @name mapValuesSeries
2805 * @static
2806 * @memberOf module:Collections
2807 * @method
2808 * @see [async.mapValues]{@link module:Collections.mapValues}
2809 * @category Collection
2810 * @param {Object} obj - A collection to iterate over.
2811 * @param {AsyncFunction} iteratee - A function to apply to each value and key
2812 * in `coll`.
2813 * The iteratee should complete with the transformed value as its result.
2814 * Invoked with (value, key, callback).
2815 * @param {Function} [callback] - A callback which is called when all `iteratee`
2816 * functions have finished, or an error occurs. `result` is a new object consisting
2817 * of each key from `obj`, with each transformed value on the right-hand side.
2818 * Invoked with (err, result).
2819 * @returns {Promise} a promise, if no callback is passed
2820 */
2821function mapValuesSeries(obj, iteratee, callback) {
2822 return mapValuesLimit$1(obj, 1, iteratee, callback)
2823}
2824
2825/**
2826 * Caches the results of an async function. When creating a hash to store
2827 * function results against, the callback is omitted from the hash and an
2828 * optional hash function can be used.
2829 *
2830 * **Note: if the async function errs, the result will not be cached and
2831 * subsequent calls will call the wrapped function.**
2832 *
2833 * If no hash function is specified, the first argument is used as a hash key,
2834 * which may work reasonably if it is a string or a data type that converts to a
2835 * distinct string. Note that objects and arrays will not behave reasonably.
2836 * Neither will cases where the other arguments are significant. In such cases,
2837 * specify your own hash function.
2838 *
2839 * The cache of results is exposed as the `memo` property of the function
2840 * returned by `memoize`.
2841 *
2842 * @name memoize
2843 * @static
2844 * @memberOf module:Utils
2845 * @method
2846 * @category Util
2847 * @param {AsyncFunction} fn - The async function to proxy and cache results from.
2848 * @param {Function} hasher - An optional function for generating a custom hash
2849 * for storing results. It has all the arguments applied to it apart from the
2850 * callback, and must be synchronous.
2851 * @returns {AsyncFunction} a memoized version of `fn`
2852 * @example
2853 *
2854 * var slow_fn = function(name, callback) {
2855 * // do something
2856 * callback(null, result);
2857 * };
2858 * var fn = async.memoize(slow_fn);
2859 *
2860 * // fn can now be used as if it were slow_fn
2861 * fn('some name', function() {
2862 * // callback
2863 * });
2864 */
2865function memoize(fn, hasher = v => v) {
2866 var memo = Object.create(null);
2867 var queues = Object.create(null);
2868 var _fn = wrapAsync(fn);
2869 var memoized = initialParams((args, callback) => {
2870 var key = hasher(...args);
2871 if (key in memo) {
2872 setImmediate$1(() => callback(null, ...memo[key]));
2873 } else if (key in queues) {
2874 queues[key].push(callback);
2875 } else {
2876 queues[key] = [callback];
2877 _fn(...args, (err, ...resultArgs) => {
2878 // #1465 don't memoize if an error occurred
2879 if (!err) {
2880 memo[key] = resultArgs;
2881 }
2882 var q = queues[key];
2883 delete queues[key];
2884 for (var i = 0, l = q.length; i < l; i++) {
2885 q[i](err, ...resultArgs);
2886 }
2887 });
2888 }
2889 });
2890 memoized.memo = memo;
2891 memoized.unmemoized = fn;
2892 return memoized;
2893}
2894
2895/**
2896 * Calls `callback` on a later loop around the event loop. In Node.js this just
2897 * calls `process.nextTick`. In the browser it will use `setImmediate` if
2898 * available, otherwise `setTimeout(callback, 0)`, which means other higher
2899 * priority events may precede the execution of `callback`.
2900 *
2901 * This is used internally for browser-compatibility purposes.
2902 *
2903 * @name nextTick
2904 * @static
2905 * @memberOf module:Utils
2906 * @method
2907 * @see [async.setImmediate]{@link module:Utils.setImmediate}
2908 * @category Util
2909 * @param {Function} callback - The function to call on a later loop around
2910 * the event loop. Invoked with (args...).
2911 * @param {...*} args... - any number of additional arguments to pass to the
2912 * callback on the next tick.
2913 * @example
2914 *
2915 * var call_order = [];
2916 * async.nextTick(function() {
2917 * call_order.push('two');
2918 * // call_order now equals ['one','two']
2919 * });
2920 * call_order.push('one');
2921 *
2922 * async.setImmediate(function (a, b, c) {
2923 * // a, b, and c equal 1, 2, and 3
2924 * }, 1, 2, 3);
2925 */
2926var _defer$1;
2927
2928if (hasNextTick) {
2929 _defer$1 = process.nextTick;
2930} else if (hasSetImmediate) {
2931 _defer$1 = setImmediate;
2932} else {
2933 _defer$1 = fallback;
2934}
2935
2936var nextTick = wrap(_defer$1);
2937
2938var _parallel = awaitify((eachfn, tasks, callback) => {
2939 var results = isArrayLike(tasks) ? [] : {};
2940
2941 eachfn(tasks, (task, key, taskCb) => {
2942 wrapAsync(task)((err, ...result) => {
2943 if (result.length < 2) {
2944 [result] = result;
2945 }
2946 results[key] = result;
2947 taskCb(err);
2948 });
2949 }, err => callback(err, results));
2950}, 3);
2951
2952/**
2953 * Run the `tasks` collection of functions in parallel, without waiting until
2954 * the previous function has completed. If any of the functions pass an error to
2955 * its callback, the main `callback` is immediately called with the value of the
2956 * error. Once the `tasks` have completed, the results are passed to the final
2957 * `callback` as an array.
2958 *
2959 * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about
2960 * parallel execution of code. If your tasks do not use any timers or perform
2961 * any I/O, they will actually be executed in series. Any synchronous setup
2962 * sections for each task will happen one after the other. JavaScript remains
2963 * single-threaded.
2964 *
2965 * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the
2966 * execution of other tasks when a task fails.
2967 *
2968 * It is also possible to use an object instead of an array. Each property will
2969 * be run as a function and the results will be passed to the final `callback`
2970 * as an object instead of an array. This can be a more readable way of handling
2971 * results from {@link async.parallel}.
2972 *
2973 * @name parallel
2974 * @static
2975 * @memberOf module:ControlFlow
2976 * @method
2977 * @category Control Flow
2978 * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
2979 * [async functions]{@link AsyncFunction} to run.
2980 * Each async function can complete with any number of optional `result` values.
2981 * @param {Function} [callback] - An optional callback to run once all the
2982 * functions have completed successfully. This function gets a results array
2983 * (or object) containing all the result arguments passed to the task callbacks.
2984 * Invoked with (err, results).
2985 * @returns {Promise} a promise, if a callback is not passed
2986 *
2987 * @example
2988 * async.parallel([
2989 * function(callback) {
2990 * setTimeout(function() {
2991 * callback(null, 'one');
2992 * }, 200);
2993 * },
2994 * function(callback) {
2995 * setTimeout(function() {
2996 * callback(null, 'two');
2997 * }, 100);
2998 * }
2999 * ],
3000 * // optional callback
3001 * function(err, results) {
3002 * // the results array will equal ['one','two'] even though
3003 * // the second function had a shorter timeout.
3004 * });
3005 *
3006 * // an example using an object instead of an array
3007 * async.parallel({
3008 * one: function(callback) {
3009 * setTimeout(function() {
3010 * callback(null, 1);
3011 * }, 200);
3012 * },
3013 * two: function(callback) {
3014 * setTimeout(function() {
3015 * callback(null, 2);
3016 * }, 100);
3017 * }
3018 * }, function(err, results) {
3019 * // results is now equals to: {one: 1, two: 2}
3020 * });
3021 */
3022function parallel(tasks, callback) {
3023 return _parallel(eachOf$1, tasks, callback);
3024}
3025
3026/**
3027 * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a
3028 * time.
3029 *
3030 * @name parallelLimit
3031 * @static
3032 * @memberOf module:ControlFlow
3033 * @method
3034 * @see [async.parallel]{@link module:ControlFlow.parallel}
3035 * @category Control Flow
3036 * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
3037 * [async functions]{@link AsyncFunction} to run.
3038 * Each async function can complete with any number of optional `result` values.
3039 * @param {number} limit - The maximum number of async operations at a time.
3040 * @param {Function} [callback] - An optional callback to run once all the
3041 * functions have completed successfully. This function gets a results array
3042 * (or object) containing all the result arguments passed to the task callbacks.
3043 * Invoked with (err, results).
3044 * @returns {Promise} a promise, if a callback is not passed
3045 */
3046function parallelLimit(tasks, limit, callback) {
3047 return _parallel(eachOfLimit(limit), tasks, callback);
3048}
3049
3050/**
3051 * A queue of tasks for the worker function to complete.
3052 * @typedef {Iterable} QueueObject
3053 * @memberOf module:ControlFlow
3054 * @property {Function} length - a function returning the number of items
3055 * waiting to be processed. Invoke with `queue.length()`.
3056 * @property {boolean} started - a boolean indicating whether or not any
3057 * items have been pushed and processed by the queue.
3058 * @property {Function} running - a function returning the number of items
3059 * currently being processed. Invoke with `queue.running()`.
3060 * @property {Function} workersList - a function returning the array of items
3061 * currently being processed. Invoke with `queue.workersList()`.
3062 * @property {Function} idle - a function returning false if there are items
3063 * waiting or being processed, or true if not. Invoke with `queue.idle()`.
3064 * @property {number} concurrency - an integer for determining how many `worker`
3065 * functions should be run in parallel. This property can be changed after a
3066 * `queue` is created to alter the concurrency on-the-fly.
3067 * @property {number} payload - an integer that specifies how many items are
3068 * passed to the worker function at a time. only applies if this is a
3069 * [cargo]{@link module:ControlFlow.cargo} object
3070 * @property {AsyncFunction} push - add a new task to the `queue`. Calls `callback`
3071 * once the `worker` has finished processing the task. Instead of a single task,
3072 * a `tasks` array can be submitted. The respective callback is used for every
3073 * task in the list. Invoke with `queue.push(task, [callback])`,
3074 * @property {AsyncFunction} unshift - add a new task to the front of the `queue`.
3075 * Invoke with `queue.unshift(task, [callback])`.
3076 * @property {AsyncFunction} pushAsync - the same as `q.push`, except this returns
3077 * a promise that rejects if an error occurs.
3078 * @property {AsyncFunction} unshirtAsync - the same as `q.unshift`, except this returns
3079 * a promise that rejects if an error occurs.
3080 * @property {Function} remove - remove items from the queue that match a test
3081 * function. The test function will be passed an object with a `data` property,
3082 * and a `priority` property, if this is a
3083 * [priorityQueue]{@link module:ControlFlow.priorityQueue} object.
3084 * Invoked with `queue.remove(testFn)`, where `testFn` is of the form
3085 * `function ({data, priority}) {}` and returns a Boolean.
3086 * @property {Function} saturated - a function that sets a callback that is
3087 * called when the number of running workers hits the `concurrency` limit, and
3088 * further tasks will be queued. If the callback is omitted, `q.saturated()`
3089 * returns a promise for the next occurrence.
3090 * @property {Function} unsaturated - a function that sets a callback that is
3091 * called when the number of running workers is less than the `concurrency` &
3092 * `buffer` limits, and further tasks will not be queued. If the callback is
3093 * omitted, `q.unsaturated()` returns a promise for the next occurrence.
3094 * @property {number} buffer - A minimum threshold buffer in order to say that
3095 * the `queue` is `unsaturated`.
3096 * @property {Function} empty - a function that sets a callback that is called
3097 * when the last item from the `queue` is given to a `worker`. If the callback
3098 * is omitted, `q.empty()` returns a promise for the next occurrence.
3099 * @property {Function} drain - a function that sets a callback that is called
3100 * when the last item from the `queue` has returned from the `worker`. If the
3101 * callback is omitted, `q.drain()` returns a promise for the next occurrence.
3102 * @property {Function} error - a function that sets a callback that is called
3103 * when a task errors. Has the signature `function(error, task)`. If the
3104 * callback is omitted, `error()` returns a promise that rejects on the next
3105 * error.
3106 * @property {boolean} paused - a boolean for determining whether the queue is
3107 * in a paused state.
3108 * @property {Function} pause - a function that pauses the processing of tasks
3109 * until `resume()` is called. Invoke with `queue.pause()`.
3110 * @property {Function} resume - a function that resumes the processing of
3111 * queued tasks when the queue is paused. Invoke with `queue.resume()`.
3112 * @property {Function} kill - a function that removes the `drain` callback and
3113 * empties remaining tasks from the queue forcing it to go idle. No more tasks
3114 * should be pushed to the queue after calling this function. Invoke with `queue.kill()`.
3115 *
3116 * @example
3117 * const q = aync.queue(worker, 2)
3118 * q.push(item1)
3119 * q.push(item2)
3120 * q.push(item3)
3121 * // queues are iterable, spread into an array to inspect
3122 * const items = [...q] // [item1, item2, item3]
3123 * // or use for of
3124 * for (let item of q) {
3125 * console.log(item)
3126 * }
3127 *
3128 * q.drain(() => {
3129 * console.log('all done')
3130 * })
3131 * // or
3132 * await q.drain()
3133 */
3134
3135/**
3136 * Creates a `queue` object with the specified `concurrency`. Tasks added to the
3137 * `queue` are processed in parallel (up to the `concurrency` limit). If all
3138 * `worker`s are in progress, the task is queued until one becomes available.
3139 * Once a `worker` completes a `task`, that `task`'s callback is called.
3140 *
3141 * @name queue
3142 * @static
3143 * @memberOf module:ControlFlow
3144 * @method
3145 * @category Control Flow
3146 * @param {AsyncFunction} worker - An async function for processing a queued task.
3147 * If you want to handle errors from an individual task, pass a callback to
3148 * `q.push()`. Invoked with (task, callback).
3149 * @param {number} [concurrency=1] - An `integer` for determining how many
3150 * `worker` functions should be run in parallel. If omitted, the concurrency
3151 * defaults to `1`. If the concurrency is `0`, an error is thrown.
3152 * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can be
3153 * attached as certain properties to listen for specific events during the
3154 * lifecycle of the queue.
3155 * @example
3156 *
3157 * // create a queue object with concurrency 2
3158 * var q = async.queue(function(task, callback) {
3159 * console.log('hello ' + task.name);
3160 * callback();
3161 * }, 2);
3162 *
3163 * // assign a callback
3164 * q.drain(function() {
3165 * console.log('all items have been processed');
3166 * });
3167 * // or await the end
3168 * await q.drain()
3169 *
3170 * // assign an error callback
3171 * q.error(function(err, task) {
3172 * console.error('task experienced an error');
3173 * });
3174 *
3175 * // add some items to the queue
3176 * q.push({name: 'foo'}, function(err) {
3177 * console.log('finished processing foo');
3178 * });
3179 * // callback is optional
3180 * q.push({name: 'bar'});
3181 *
3182 * // add some items to the queue (batch-wise)
3183 * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
3184 * console.log('finished processing item');
3185 * });
3186 *
3187 * // add some items to the front of the queue
3188 * q.unshift({name: 'bar'}, function (err) {
3189 * console.log('finished processing bar');
3190 * });
3191 */
3192function queue$1 (worker, concurrency) {
3193 var _worker = wrapAsync(worker);
3194 return queue((items, cb) => {
3195 _worker(items[0], cb);
3196 }, concurrency, 1);
3197}
3198
3199// Binary min-heap implementation used for priority queue.
3200// Implementation is stable, i.e. push time is considered for equal priorities
3201class Heap {
3202 constructor() {
3203 this.heap = [];
3204 this.pushCount = Number.MIN_SAFE_INTEGER;
3205 }
3206
3207 get length() {
3208 return this.heap.length;
3209 }
3210
3211 empty () {
3212 this.heap = [];
3213 return this;
3214 }
3215
3216 percUp(index) {
3217 let p;
3218
3219 while (index > 0 && smaller(this.heap[index], this.heap[p=parent(index)])) {
3220 let t = this.heap[index];
3221 this.heap[index] = this.heap[p];
3222 this.heap[p] = t;
3223
3224 index = p;
3225 }
3226 }
3227
3228 percDown(index) {
3229 let l;
3230
3231 while ((l=leftChi(index)) < this.heap.length) {
3232 if (l+1 < this.heap.length && smaller(this.heap[l+1], this.heap[l])) {
3233 l = l+1;
3234 }
3235
3236 if (smaller(this.heap[index], this.heap[l])) {
3237 break;
3238 }
3239
3240 let t = this.heap[index];
3241 this.heap[index] = this.heap[l];
3242 this.heap[l] = t;
3243
3244 index = l;
3245 }
3246 }
3247
3248 push(node) {
3249 node.pushCount = ++this.pushCount;
3250 this.heap.push(node);
3251 this.percUp(this.heap.length-1);
3252 }
3253
3254 unshift(node) {
3255 return this.heap.push(node);
3256 }
3257
3258 shift() {
3259 let [top] = this.heap;
3260
3261 this.heap[0] = this.heap[this.heap.length-1];
3262 this.heap.pop();
3263 this.percDown(0);
3264
3265 return top;
3266 }
3267
3268 toArray() {
3269 return [...this];
3270 }
3271
3272 *[Symbol.iterator] () {
3273 for (let i = 0; i < this.heap.length; i++) {
3274 yield this.heap[i].data;
3275 }
3276 }
3277
3278 remove (testFn) {
3279 let j = 0;
3280 for (let i = 0; i < this.heap.length; i++) {
3281 if (!testFn(this.heap[i])) {
3282 this.heap[j] = this.heap[i];
3283 j++;
3284 }
3285 }
3286
3287 this.heap.splice(j);
3288
3289 for (let i = parent(this.heap.length-1); i >= 0; i--) {
3290 this.percDown(i);
3291 }
3292
3293 return this;
3294 }
3295}
3296
3297function leftChi(i) {
3298 return (i<<1)+1;
3299}
3300
3301function parent(i) {
3302 return ((i+1)>>1)-1;
3303}
3304
3305function smaller(x, y) {
3306 if (x.priority !== y.priority) {
3307 return x.priority < y.priority;
3308 }
3309 else {
3310 return x.pushCount < y.pushCount;
3311 }
3312}
3313
3314/**
3315 * The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and
3316 * completed in ascending priority order.
3317 *
3318 * @name priorityQueue
3319 * @static
3320 * @memberOf module:ControlFlow
3321 * @method
3322 * @see [async.queue]{@link module:ControlFlow.queue}
3323 * @category Control Flow
3324 * @param {AsyncFunction} worker - An async function for processing a queued task.
3325 * If you want to handle errors from an individual task, pass a callback to
3326 * `q.push()`.
3327 * Invoked with (task, callback).
3328 * @param {number} concurrency - An `integer` for determining how many `worker`
3329 * functions should be run in parallel. If omitted, the concurrency defaults to
3330 * `1`. If the concurrency is `0`, an error is thrown.
3331 * @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are two
3332 * differences between `queue` and `priorityQueue` objects:
3333 * * `push(task, priority, [callback])` - `priority` should be a number. If an
3334 * array of `tasks` is given, all tasks will be assigned the same priority.
3335 * * The `unshift` method was removed.
3336 */
3337function priorityQueue(worker, concurrency) {
3338 // Start with a normal queue
3339 var q = queue$1(worker, concurrency);
3340
3341 q._tasks = new Heap();
3342
3343 // Override push to accept second parameter representing priority
3344 q.push = function(data, priority = 0, callback = () => {}) {
3345 if (typeof callback !== 'function') {
3346 throw new Error('task callback must be a function');
3347 }
3348 q.started = true;
3349 if (!Array.isArray(data)) {
3350 data = [data];
3351 }
3352 if (data.length === 0 && q.idle()) {
3353 // call drain immediately if there are no tasks
3354 return setImmediate$1(() => q.drain());
3355 }
3356
3357 for (var i = 0, l = data.length; i < l; i++) {
3358 var item = {
3359 data: data[i],
3360 priority,
3361 callback
3362 };
3363
3364 q._tasks.push(item);
3365 }
3366
3367 setImmediate$1(q.process);
3368 };
3369
3370 // Remove unshift function
3371 delete q.unshift;
3372
3373 return q;
3374}
3375
3376/**
3377 * Runs the `tasks` array of functions in parallel, without waiting until the
3378 * previous function has completed. Once any of the `tasks` complete or pass an
3379 * error to its callback, the main `callback` is immediately called. It's
3380 * equivalent to `Promise.race()`.
3381 *
3382 * @name race
3383 * @static
3384 * @memberOf module:ControlFlow
3385 * @method
3386 * @category Control Flow
3387 * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction}
3388 * to run. Each function can complete with an optional `result` value.
3389 * @param {Function} callback - A callback to run once any of the functions have
3390 * completed. This function gets an error or result from the first function that
3391 * completed. Invoked with (err, result).
3392 * @returns undefined
3393 * @example
3394 *
3395 * async.race([
3396 * function(callback) {
3397 * setTimeout(function() {
3398 * callback(null, 'one');
3399 * }, 200);
3400 * },
3401 * function(callback) {
3402 * setTimeout(function() {
3403 * callback(null, 'two');
3404 * }, 100);
3405 * }
3406 * ],
3407 * // main callback
3408 * function(err, result) {
3409 * // the result will be equal to 'two' as it finishes earlier
3410 * });
3411 */
3412function race(tasks, callback) {
3413 callback = once(callback);
3414 if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions'));
3415 if (!tasks.length) return callback();
3416 for (var i = 0, l = tasks.length; i < l; i++) {
3417 wrapAsync(tasks[i])(callback);
3418 }
3419}
3420
3421var race$1 = awaitify(race, 2);
3422
3423/**
3424 * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order.
3425 *
3426 * @name reduceRight
3427 * @static
3428 * @memberOf module:Collections
3429 * @method
3430 * @see [async.reduce]{@link module:Collections.reduce}
3431 * @alias foldr
3432 * @category Collection
3433 * @param {Array} array - A collection to iterate over.
3434 * @param {*} memo - The initial state of the reduction.
3435 * @param {AsyncFunction} iteratee - A function applied to each item in the
3436 * array to produce the next step in the reduction.
3437 * The `iteratee` should complete with the next state of the reduction.
3438 * If the iteratee complete with an error, the reduction is stopped and the
3439 * main `callback` is immediately called with the error.
3440 * Invoked with (memo, item, callback).
3441 * @param {Function} [callback] - A callback which is called after all the
3442 * `iteratee` functions have finished. Result is the reduced value. Invoked with
3443 * (err, result).
3444 * @returns {Promise} a promise, if no callback is passed
3445 */
3446function reduceRight (array, memo, iteratee, callback) {
3447 var reversed = [...array].reverse();
3448 return reduce$1(reversed, memo, iteratee, callback);
3449}
3450
3451/**
3452 * Wraps the async function in another function that always completes with a
3453 * result object, even when it errors.
3454 *
3455 * The result object has either the property `error` or `value`.
3456 *
3457 * @name reflect
3458 * @static
3459 * @memberOf module:Utils
3460 * @method
3461 * @category Util
3462 * @param {AsyncFunction} fn - The async function you want to wrap
3463 * @returns {Function} - A function that always passes null to it's callback as
3464 * the error. The second argument to the callback will be an `object` with
3465 * either an `error` or a `value` property.
3466 * @example
3467 *
3468 * async.parallel([
3469 * async.reflect(function(callback) {
3470 * // do some stuff ...
3471 * callback(null, 'one');
3472 * }),
3473 * async.reflect(function(callback) {
3474 * // do some more stuff but error ...
3475 * callback('bad stuff happened');
3476 * }),
3477 * async.reflect(function(callback) {
3478 * // do some more stuff ...
3479 * callback(null, 'two');
3480 * })
3481 * ],
3482 * // optional callback
3483 * function(err, results) {
3484 * // values
3485 * // results[0].value = 'one'
3486 * // results[1].error = 'bad stuff happened'
3487 * // results[2].value = 'two'
3488 * });
3489 */
3490function reflect(fn) {
3491 var _fn = wrapAsync(fn);
3492 return initialParams(function reflectOn(args, reflectCallback) {
3493 args.push((error, ...cbArgs) => {
3494 let retVal = {};
3495 if (error) {
3496 retVal.error = error;
3497 }
3498 if (cbArgs.length > 0){
3499 var value = cbArgs;
3500 if (cbArgs.length <= 1) {
3501 [value] = cbArgs;
3502 }
3503 retVal.value = value;
3504 }
3505 reflectCallback(null, retVal);
3506 });
3507
3508 return _fn.apply(this, args);
3509 });
3510}
3511
3512/**
3513 * A helper function that wraps an array or an object of functions with `reflect`.
3514 *
3515 * @name reflectAll
3516 * @static
3517 * @memberOf module:Utils
3518 * @method
3519 * @see [async.reflect]{@link module:Utils.reflect}
3520 * @category Util
3521 * @param {Array|Object|Iterable} tasks - The collection of
3522 * [async functions]{@link AsyncFunction} to wrap in `async.reflect`.
3523 * @returns {Array} Returns an array of async functions, each wrapped in
3524 * `async.reflect`
3525 * @example
3526 *
3527 * let tasks = [
3528 * function(callback) {
3529 * setTimeout(function() {
3530 * callback(null, 'one');
3531 * }, 200);
3532 * },
3533 * function(callback) {
3534 * // do some more stuff but error ...
3535 * callback(new Error('bad stuff happened'));
3536 * },
3537 * function(callback) {
3538 * setTimeout(function() {
3539 * callback(null, 'two');
3540 * }, 100);
3541 * }
3542 * ];
3543 *
3544 * async.parallel(async.reflectAll(tasks),
3545 * // optional callback
3546 * function(err, results) {
3547 * // values
3548 * // results[0].value = 'one'
3549 * // results[1].error = Error('bad stuff happened')
3550 * // results[2].value = 'two'
3551 * });
3552 *
3553 * // an example using an object instead of an array
3554 * let tasks = {
3555 * one: function(callback) {
3556 * setTimeout(function() {
3557 * callback(null, 'one');
3558 * }, 200);
3559 * },
3560 * two: function(callback) {
3561 * callback('two');
3562 * },
3563 * three: function(callback) {
3564 * setTimeout(function() {
3565 * callback(null, 'three');
3566 * }, 100);
3567 * }
3568 * };
3569 *
3570 * async.parallel(async.reflectAll(tasks),
3571 * // optional callback
3572 * function(err, results) {
3573 * // values
3574 * // results.one.value = 'one'
3575 * // results.two.error = 'two'
3576 * // results.three.value = 'three'
3577 * });
3578 */
3579function reflectAll(tasks) {
3580 var results;
3581 if (Array.isArray(tasks)) {
3582 results = tasks.map(reflect);
3583 } else {
3584 results = {};
3585 Object.keys(tasks).forEach(key => {
3586 results[key] = reflect.call(this, tasks[key]);
3587 });
3588 }
3589 return results;
3590}
3591
3592function reject(eachfn, arr, _iteratee, callback) {
3593 const iteratee = wrapAsync(_iteratee);
3594 return _filter(eachfn, arr, (value, cb) => {
3595 iteratee(value, (err, v) => {
3596 cb(err, !v);
3597 });
3598 }, callback);
3599}
3600
3601/**
3602 * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test.
3603 *
3604 * @name reject
3605 * @static
3606 * @memberOf module:Collections
3607 * @method
3608 * @see [async.filter]{@link module:Collections.filter}
3609 * @category Collection
3610 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
3611 * @param {Function} iteratee - An async truth test to apply to each item in
3612 * `coll`.
3613 * The should complete with a boolean value as its `result`.
3614 * Invoked with (item, callback).
3615 * @param {Function} [callback] - A callback which is called after all the
3616 * `iteratee` functions have finished. Invoked with (err, results).
3617 * @returns {Promise} a promise, if no callback is passed
3618 * @example
3619 *
3620 * async.reject(['file1','file2','file3'], function(filePath, callback) {
3621 * fs.access(filePath, function(err) {
3622 * callback(null, !err)
3623 * });
3624 * }, function(err, results) {
3625 * // results now equals an array of missing files
3626 * createFiles(results);
3627 * });
3628 */
3629function reject$1 (coll, iteratee, callback) {
3630 return reject(eachOf$1, coll, iteratee, callback)
3631}
3632var reject$2 = awaitify(reject$1, 3);
3633
3634/**
3635 * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a
3636 * time.
3637 *
3638 * @name rejectLimit
3639 * @static
3640 * @memberOf module:Collections
3641 * @method
3642 * @see [async.reject]{@link module:Collections.reject}
3643 * @category Collection
3644 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
3645 * @param {number} limit - The maximum number of async operations at a time.
3646 * @param {Function} iteratee - An async truth test to apply to each item in
3647 * `coll`.
3648 * The should complete with a boolean value as its `result`.
3649 * Invoked with (item, callback).
3650 * @param {Function} [callback] - A callback which is called after all the
3651 * `iteratee` functions have finished. Invoked with (err, results).
3652 * @returns {Promise} a promise, if no callback is passed
3653 */
3654function rejectLimit (coll, limit, iteratee, callback) {
3655 return reject(eachOfLimit(limit), coll, iteratee, callback)
3656}
3657var rejectLimit$1 = awaitify(rejectLimit, 4);
3658
3659/**
3660 * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time.
3661 *
3662 * @name rejectSeries
3663 * @static
3664 * @memberOf module:Collections
3665 * @method
3666 * @see [async.reject]{@link module:Collections.reject}
3667 * @category Collection
3668 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
3669 * @param {Function} iteratee - An async truth test to apply to each item in
3670 * `coll`.
3671 * The should complete with a boolean value as its `result`.
3672 * Invoked with (item, callback).
3673 * @param {Function} [callback] - A callback which is called after all the
3674 * `iteratee` functions have finished. Invoked with (err, results).
3675 * @returns {Promise} a promise, if no callback is passed
3676 */
3677function rejectSeries (coll, iteratee, callback) {
3678 return reject(eachOfSeries$1, coll, iteratee, callback)
3679}
3680var rejectSeries$1 = awaitify(rejectSeries, 3);
3681
3682function constant$1(value) {
3683 return function () {
3684 return value;
3685 }
3686}
3687
3688/**
3689 * Attempts to get a successful response from `task` no more than `times` times
3690 * before returning an error. If the task is successful, the `callback` will be
3691 * passed the result of the successful task. If all attempts fail, the callback
3692 * will be passed the error and result (if any) of the final attempt.
3693 *
3694 * @name retry
3695 * @static
3696 * @memberOf module:ControlFlow
3697 * @method
3698 * @category Control Flow
3699 * @see [async.retryable]{@link module:ControlFlow.retryable}
3700 * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an
3701 * object with `times` and `interval` or a number.
3702 * * `times` - The number of attempts to make before giving up. The default
3703 * is `5`.
3704 * * `interval` - The time to wait between retries, in milliseconds. The
3705 * default is `0`. The interval may also be specified as a function of the
3706 * retry count (see example).
3707 * * `errorFilter` - An optional synchronous function that is invoked on
3708 * erroneous result. If it returns `true` the retry attempts will continue;
3709 * if the function returns `false` the retry flow is aborted with the current
3710 * attempt's error and result being returned to the final callback.
3711 * Invoked with (err).
3712 * * If `opts` is a number, the number specifies the number of times to retry,
3713 * with the default interval of `0`.
3714 * @param {AsyncFunction} task - An async function to retry.
3715 * Invoked with (callback).
3716 * @param {Function} [callback] - An optional callback which is called when the
3717 * task has succeeded, or after the final failed attempt. It receives the `err`
3718 * and `result` arguments of the last attempt at completing the `task`. Invoked
3719 * with (err, results).
3720 * @returns {Promise} a promise if no callback provided
3721 *
3722 * @example
3723 *
3724 * // The `retry` function can be used as a stand-alone control flow by passing
3725 * // a callback, as shown below:
3726 *
3727 * // try calling apiMethod 3 times
3728 * async.retry(3, apiMethod, function(err, result) {
3729 * // do something with the result
3730 * });
3731 *
3732 * // try calling apiMethod 3 times, waiting 200 ms between each retry
3733 * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
3734 * // do something with the result
3735 * });
3736 *
3737 * // try calling apiMethod 10 times with exponential backoff
3738 * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds)
3739 * async.retry({
3740 * times: 10,
3741 * interval: function(retryCount) {
3742 * return 50 * Math.pow(2, retryCount);
3743 * }
3744 * }, apiMethod, function(err, result) {
3745 * // do something with the result
3746 * });
3747 *
3748 * // try calling apiMethod the default 5 times no delay between each retry
3749 * async.retry(apiMethod, function(err, result) {
3750 * // do something with the result
3751 * });
3752 *
3753 * // try calling apiMethod only when error condition satisfies, all other
3754 * // errors will abort the retry control flow and return to final callback
3755 * async.retry({
3756 * errorFilter: function(err) {
3757 * return err.message === 'Temporary error'; // only retry on a specific error
3758 * }
3759 * }, apiMethod, function(err, result) {
3760 * // do something with the result
3761 * });
3762 *
3763 * // to retry individual methods that are not as reliable within other
3764 * // control flow functions, use the `retryable` wrapper:
3765 * async.auto({
3766 * users: api.getUsers.bind(api),
3767 * payments: async.retryable(3, api.getPayments.bind(api))
3768 * }, function(err, results) {
3769 * // do something with the results
3770 * });
3771 *
3772 */
3773const DEFAULT_TIMES = 5;
3774const DEFAULT_INTERVAL = 0;
3775
3776function retry(opts, task, callback) {
3777 var options = {
3778 times: DEFAULT_TIMES,
3779 intervalFunc: constant$1(DEFAULT_INTERVAL)
3780 };
3781
3782 if (arguments.length < 3 && typeof opts === 'function') {
3783 callback = task || promiseCallback();
3784 task = opts;
3785 } else {
3786 parseTimes(options, opts);
3787 callback = callback || promiseCallback();
3788 }
3789
3790 if (typeof task !== 'function') {
3791 throw new Error("Invalid arguments for async.retry");
3792 }
3793
3794 var _task = wrapAsync(task);
3795
3796 var attempt = 1;
3797 function retryAttempt() {
3798 _task((err, ...args) => {
3799 if (err === false) return
3800 if (err && attempt++ < options.times &&
3801 (typeof options.errorFilter != 'function' ||
3802 options.errorFilter(err))) {
3803 setTimeout(retryAttempt, options.intervalFunc(attempt - 1));
3804 } else {
3805 callback(err, ...args);
3806 }
3807 });
3808 }
3809
3810 retryAttempt();
3811 return callback[PROMISE_SYMBOL]
3812}
3813
3814function parseTimes(acc, t) {
3815 if (typeof t === 'object') {
3816 acc.times = +t.times || DEFAULT_TIMES;
3817
3818 acc.intervalFunc = typeof t.interval === 'function' ?
3819 t.interval :
3820 constant$1(+t.interval || DEFAULT_INTERVAL);
3821
3822 acc.errorFilter = t.errorFilter;
3823 } else if (typeof t === 'number' || typeof t === 'string') {
3824 acc.times = +t || DEFAULT_TIMES;
3825 } else {
3826 throw new Error("Invalid arguments for async.retry");
3827 }
3828}
3829
3830/**
3831 * A close relative of [`retry`]{@link module:ControlFlow.retry}. This method
3832 * wraps a task and makes it retryable, rather than immediately calling it
3833 * with retries.
3834 *
3835 * @name retryable
3836 * @static
3837 * @memberOf module:ControlFlow
3838 * @method
3839 * @see [async.retry]{@link module:ControlFlow.retry}
3840 * @category Control Flow
3841 * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional
3842 * options, exactly the same as from `retry`, except for a `opts.arity` that
3843 * is the arity of the `task` function, defaulting to `task.length`
3844 * @param {AsyncFunction} task - the asynchronous function to wrap.
3845 * This function will be passed any arguments passed to the returned wrapper.
3846 * Invoked with (...args, callback).
3847 * @returns {AsyncFunction} The wrapped function, which when invoked, will
3848 * retry on an error, based on the parameters specified in `opts`.
3849 * This function will accept the same parameters as `task`.
3850 * @example
3851 *
3852 * async.auto({
3853 * dep1: async.retryable(3, getFromFlakyService),
3854 * process: ["dep1", async.retryable(3, function (results, cb) {
3855 * maybeProcessData(results.dep1, cb);
3856 * })]
3857 * }, callback);
3858 */
3859function retryable (opts, task) {
3860 if (!task) {
3861 task = opts;
3862 opts = null;
3863 }
3864 let arity = (opts && opts.arity) || task.length;
3865 if (isAsync(task)) {
3866 arity += 1;
3867 }
3868 var _task = wrapAsync(task);
3869 return initialParams((args, callback) => {
3870 if (args.length < arity - 1 || callback == null) {
3871 args.push(callback);
3872 callback = promiseCallback();
3873 }
3874 function taskFn(cb) {
3875 _task(...args, cb);
3876 }
3877
3878 if (opts) retry(opts, taskFn, callback);
3879 else retry(taskFn, callback);
3880
3881 return callback[PROMISE_SYMBOL]
3882 });
3883}
3884
3885/**
3886 * Run the functions in the `tasks` collection in series, each one running once
3887 * the previous function has completed. If any functions in the series pass an
3888 * error to its callback, no more functions are run, and `callback` is
3889 * immediately called with the value of the error. Otherwise, `callback`
3890 * receives an array of results when `tasks` have completed.
3891 *
3892 * It is also possible to use an object instead of an array. Each property will
3893 * be run as a function, and the results will be passed to the final `callback`
3894 * as an object instead of an array. This can be a more readable way of handling
3895 * results from {@link async.series}.
3896 *
3897 * **Note** that while many implementations preserve the order of object
3898 * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6)
3899 * explicitly states that
3900 *
3901 * > The mechanics and order of enumerating the properties is not specified.
3902 *
3903 * So if you rely on the order in which your series of functions are executed,
3904 * and want this to work on all platforms, consider using an array.
3905 *
3906 * @name series
3907 * @static
3908 * @memberOf module:ControlFlow
3909 * @method
3910 * @category Control Flow
3911 * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing
3912 * [async functions]{@link AsyncFunction} to run in series.
3913 * Each function can complete with any number of optional `result` values.
3914 * @param {Function} [callback] - An optional callback to run once all the
3915 * functions have completed. This function gets a results array (or object)
3916 * containing all the result arguments passed to the `task` callbacks. Invoked
3917 * with (err, result).
3918 * @return {Promise} a promise, if no callback is passed
3919 * @example
3920 * async.series([
3921 * function(callback) {
3922 * // do some stuff ...
3923 * callback(null, 'one');
3924 * },
3925 * function(callback) {
3926 * // do some more stuff ...
3927 * callback(null, 'two');
3928 * }
3929 * ],
3930 * // optional callback
3931 * function(err, results) {
3932 * // results is now equal to ['one', 'two']
3933 * });
3934 *
3935 * async.series({
3936 * one: function(callback) {
3937 * setTimeout(function() {
3938 * callback(null, 1);
3939 * }, 200);
3940 * },
3941 * two: function(callback){
3942 * setTimeout(function() {
3943 * callback(null, 2);
3944 * }, 100);
3945 * }
3946 * }, function(err, results) {
3947 * // results is now equal to: {one: 1, two: 2}
3948 * });
3949 */
3950function series(tasks, callback) {
3951 return _parallel(eachOfSeries$1, tasks, callback);
3952}
3953
3954/**
3955 * Returns `true` if at least one element in the `coll` satisfies an async test.
3956 * If any iteratee call returns `true`, the main `callback` is immediately
3957 * called.
3958 *
3959 * @name some
3960 * @static
3961 * @memberOf module:Collections
3962 * @method
3963 * @alias any
3964 * @category Collection
3965 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
3966 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
3967 * in the collections in parallel.
3968 * The iteratee should complete with a boolean `result` value.
3969 * Invoked with (item, callback).
3970 * @param {Function} [callback] - A callback which is called as soon as any
3971 * iteratee returns `true`, or after all the iteratee functions have finished.
3972 * Result will be either `true` or `false` depending on the values of the async
3973 * tests. Invoked with (err, result).
3974 * @returns {Promise} a promise, if no callback provided
3975 * @example
3976 *
3977 * async.some(['file1','file2','file3'], function(filePath, callback) {
3978 * fs.access(filePath, function(err) {
3979 * callback(null, !err)
3980 * });
3981 * }, function(err, result) {
3982 * // if result is true then at least one of the files exists
3983 * });
3984 */
3985function some(coll, iteratee, callback) {
3986 return _createTester(Boolean, res => res)(eachOf$1, coll, iteratee, callback)
3987}
3988var some$1 = awaitify(some, 3);
3989
3990/**
3991 * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time.
3992 *
3993 * @name someLimit
3994 * @static
3995 * @memberOf module:Collections
3996 * @method
3997 * @see [async.some]{@link module:Collections.some}
3998 * @alias anyLimit
3999 * @category Collection
4000 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
4001 * @param {number} limit - The maximum number of async operations at a time.
4002 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
4003 * in the collections in parallel.
4004 * The iteratee should complete with a boolean `result` value.
4005 * Invoked with (item, callback).
4006 * @param {Function} [callback] - A callback which is called as soon as any
4007 * iteratee returns `true`, or after all the iteratee functions have finished.
4008 * Result will be either `true` or `false` depending on the values of the async
4009 * tests. Invoked with (err, result).
4010 * @returns {Promise} a promise, if no callback provided
4011 */
4012function someLimit(coll, limit, iteratee, callback) {
4013 return _createTester(Boolean, res => res)(eachOfLimit(limit), coll, iteratee, callback)
4014}
4015var someLimit$1 = awaitify(someLimit, 4);
4016
4017/**
4018 * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time.
4019 *
4020 * @name someSeries
4021 * @static
4022 * @memberOf module:Collections
4023 * @method
4024 * @see [async.some]{@link module:Collections.some}
4025 * @alias anySeries
4026 * @category Collection
4027 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
4028 * @param {AsyncFunction} iteratee - An async truth test to apply to each item
4029 * in the collections in series.
4030 * The iteratee should complete with a boolean `result` value.
4031 * Invoked with (item, callback).
4032 * @param {Function} [callback] - A callback which is called as soon as any
4033 * iteratee returns `true`, or after all the iteratee functions have finished.
4034 * Result will be either `true` or `false` depending on the values of the async
4035 * tests. Invoked with (err, result).
4036 * @returns {Promise} a promise, if no callback provided
4037 */
4038function someSeries(coll, iteratee, callback) {
4039 return _createTester(Boolean, res => res)(eachOfSeries$1, coll, iteratee, callback)
4040}
4041var someSeries$1 = awaitify(someSeries, 3);
4042
4043/**
4044 * Sorts a list by the results of running each `coll` value through an async
4045 * `iteratee`.
4046 *
4047 * @name sortBy
4048 * @static
4049 * @memberOf module:Collections
4050 * @method
4051 * @category Collection
4052 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
4053 * @param {AsyncFunction} iteratee - An async function to apply to each item in
4054 * `coll`.
4055 * The iteratee should complete with a value to use as the sort criteria as
4056 * its `result`.
4057 * Invoked with (item, callback).
4058 * @param {Function} callback - A callback which is called after all the
4059 * `iteratee` functions have finished, or an error occurs. Results is the items
4060 * from the original `coll` sorted by the values returned by the `iteratee`
4061 * calls. Invoked with (err, results).
4062 * @returns {Promise} a promise, if no callback passed
4063 * @example
4064 *
4065 * async.sortBy(['file1','file2','file3'], function(file, callback) {
4066 * fs.stat(file, function(err, stats) {
4067 * callback(err, stats.mtime);
4068 * });
4069 * }, function(err, results) {
4070 * // results is now the original array of files sorted by
4071 * // modified date
4072 * });
4073 *
4074 * // By modifying the callback parameter the
4075 * // sorting order can be influenced:
4076 *
4077 * // ascending order
4078 * async.sortBy([1,9,3,5], function(x, callback) {
4079 * callback(null, x);
4080 * }, function(err,result) {
4081 * // result callback
4082 * });
4083 *
4084 * // descending order
4085 * async.sortBy([1,9,3,5], function(x, callback) {
4086 * callback(null, x*-1); //<- x*-1 instead of x, turns the order around
4087 * }, function(err,result) {
4088 * // result callback
4089 * });
4090 */
4091function sortBy (coll, iteratee, callback) {
4092 var _iteratee = wrapAsync(iteratee);
4093 return map$1(coll, (x, iterCb) => {
4094 _iteratee(x, (err, criteria) => {
4095 if (err) return iterCb(err);
4096 iterCb(err, {value: x, criteria});
4097 });
4098 }, (err, results) => {
4099 if (err) return callback(err);
4100 callback(null, results.sort(comparator).map(v => v.value));
4101 });
4102
4103 function comparator(left, right) {
4104 var a = left.criteria, b = right.criteria;
4105 return a < b ? -1 : a > b ? 1 : 0;
4106 }
4107}
4108var sortBy$1 = awaitify(sortBy, 3);
4109
4110/**
4111 * Sets a time limit on an asynchronous function. If the function does not call
4112 * its callback within the specified milliseconds, it will be called with a
4113 * timeout error. The code property for the error object will be `'ETIMEDOUT'`.
4114 *
4115 * @name timeout
4116 * @static
4117 * @memberOf module:Utils
4118 * @method
4119 * @category Util
4120 * @param {AsyncFunction} asyncFn - The async function to limit in time.
4121 * @param {number} milliseconds - The specified time limit.
4122 * @param {*} [info] - Any variable you want attached (`string`, `object`, etc)
4123 * to timeout Error for more information..
4124 * @returns {AsyncFunction} Returns a wrapped function that can be used with any
4125 * of the control flow functions.
4126 * Invoke this function with the same parameters as you would `asyncFunc`.
4127 * @example
4128 *
4129 * function myFunction(foo, callback) {
4130 * doAsyncTask(foo, function(err, data) {
4131 * // handle errors
4132 * if (err) return callback(err);
4133 *
4134 * // do some stuff ...
4135 *
4136 * // return processed data
4137 * return callback(null, data);
4138 * });
4139 * }
4140 *
4141 * var wrapped = async.timeout(myFunction, 1000);
4142 *
4143 * // call `wrapped` as you would `myFunction`
4144 * wrapped({ bar: 'bar' }, function(err, data) {
4145 * // if `myFunction` takes < 1000 ms to execute, `err`
4146 * // and `data` will have their expected values
4147 *
4148 * // else `err` will be an Error with the code 'ETIMEDOUT'
4149 * });
4150 */
4151function timeout(asyncFn, milliseconds, info) {
4152 var fn = wrapAsync(asyncFn);
4153
4154 return initialParams((args, callback) => {
4155 var timedOut = false;
4156 var timer;
4157
4158 function timeoutCallback() {
4159 var name = asyncFn.name || 'anonymous';
4160 var error = new Error('Callback function "' + name + '" timed out.');
4161 error.code = 'ETIMEDOUT';
4162 if (info) {
4163 error.info = info;
4164 }
4165 timedOut = true;
4166 callback(error);
4167 }
4168
4169 args.push((...cbArgs) => {
4170 if (!timedOut) {
4171 callback(...cbArgs);
4172 clearTimeout(timer);
4173 }
4174 });
4175
4176 // setup timer and call original function
4177 timer = setTimeout(timeoutCallback, milliseconds);
4178 fn(...args);
4179 });
4180}
4181
4182function range(size) {
4183 var result = Array(size);
4184 while (size--) {
4185 result[size] = size;
4186 }
4187 return result;
4188}
4189
4190/**
4191 * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a
4192 * time.
4193 *
4194 * @name timesLimit
4195 * @static
4196 * @memberOf module:ControlFlow
4197 * @method
4198 * @see [async.times]{@link module:ControlFlow.times}
4199 * @category Control Flow
4200 * @param {number} count - The number of times to run the function.
4201 * @param {number} limit - The maximum number of async operations at a time.
4202 * @param {AsyncFunction} iteratee - The async function to call `n` times.
4203 * Invoked with the iteration index and a callback: (n, next).
4204 * @param {Function} callback - see [async.map]{@link module:Collections.map}.
4205 * @returns {Promise} a promise, if no callback is provided
4206 */
4207function timesLimit(count, limit, iteratee, callback) {
4208 var _iteratee = wrapAsync(iteratee);
4209 return mapLimit$1(range(count), limit, _iteratee, callback);
4210}
4211
4212/**
4213 * Calls the `iteratee` function `n` times, and accumulates results in the same
4214 * manner you would use with [map]{@link module:Collections.map}.
4215 *
4216 * @name times
4217 * @static
4218 * @memberOf module:ControlFlow
4219 * @method
4220 * @see [async.map]{@link module:Collections.map}
4221 * @category Control Flow
4222 * @param {number} n - The number of times to run the function.
4223 * @param {AsyncFunction} iteratee - The async function to call `n` times.
4224 * Invoked with the iteration index and a callback: (n, next).
4225 * @param {Function} callback - see {@link module:Collections.map}.
4226 * @returns {Promise} a promise, if no callback is provided
4227 * @example
4228 *
4229 * // Pretend this is some complicated async factory
4230 * var createUser = function(id, callback) {
4231 * callback(null, {
4232 * id: 'user' + id
4233 * });
4234 * };
4235 *
4236 * // generate 5 users
4237 * async.times(5, function(n, next) {
4238 * createUser(n, function(err, user) {
4239 * next(err, user);
4240 * });
4241 * }, function(err, users) {
4242 * // we should now have 5 users
4243 * });
4244 */
4245function times (n, iteratee, callback) {
4246 return timesLimit(n, Infinity, iteratee, callback)
4247}
4248
4249/**
4250 * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time.
4251 *
4252 * @name timesSeries
4253 * @static
4254 * @memberOf module:ControlFlow
4255 * @method
4256 * @see [async.times]{@link module:ControlFlow.times}
4257 * @category Control Flow
4258 * @param {number} n - The number of times to run the function.
4259 * @param {AsyncFunction} iteratee - The async function to call `n` times.
4260 * Invoked with the iteration index and a callback: (n, next).
4261 * @param {Function} callback - see {@link module:Collections.map}.
4262 * @returns {Promise} a promise, if no callback is provided
4263 */
4264function timesSeries (n, iteratee, callback) {
4265 return timesLimit(n, 1, iteratee, callback)
4266}
4267
4268/**
4269 * A relative of `reduce`. Takes an Object or Array, and iterates over each
4270 * element in parallel, each step potentially mutating an `accumulator` value.
4271 * The type of the accumulator defaults to the type of collection passed in.
4272 *
4273 * @name transform
4274 * @static
4275 * @memberOf module:Collections
4276 * @method
4277 * @category Collection
4278 * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
4279 * @param {*} [accumulator] - The initial state of the transform. If omitted,
4280 * it will default to an empty Object or Array, depending on the type of `coll`
4281 * @param {AsyncFunction} iteratee - A function applied to each item in the
4282 * collection that potentially modifies the accumulator.
4283 * Invoked with (accumulator, item, key, callback).
4284 * @param {Function} [callback] - A callback which is called after all the
4285 * `iteratee` functions have finished. Result is the transformed accumulator.
4286 * Invoked with (err, result).
4287 * @returns {Promise} a promise, if no callback provided
4288 * @example
4289 *
4290 * async.transform([1,2,3], function(acc, item, index, callback) {
4291 * // pointless async:
4292 * process.nextTick(function() {
4293 * acc[index] = item * 2
4294 * callback(null)
4295 * });
4296 * }, function(err, result) {
4297 * // result is now equal to [2, 4, 6]
4298 * });
4299 *
4300 * @example
4301 *
4302 * async.transform({a: 1, b: 2, c: 3}, function (obj, val, key, callback) {
4303 * setImmediate(function () {
4304 * obj[key] = val * 2;
4305 * callback();
4306 * })
4307 * }, function (err, result) {
4308 * // result is equal to {a: 2, b: 4, c: 6}
4309 * })
4310 */
4311function transform (coll, accumulator, iteratee, callback) {
4312 if (arguments.length <= 3 && typeof accumulator === 'function') {
4313 callback = iteratee;
4314 iteratee = accumulator;
4315 accumulator = Array.isArray(coll) ? [] : {};
4316 }
4317 callback = once(callback || promiseCallback());
4318 var _iteratee = wrapAsync(iteratee);
4319
4320 eachOf$1(coll, (v, k, cb) => {
4321 _iteratee(accumulator, v, k, cb);
4322 }, err => callback(err, accumulator));
4323 return callback[PROMISE_SYMBOL]
4324}
4325
4326/**
4327 * It runs each task in series but stops whenever any of the functions were
4328 * successful. If one of the tasks were successful, the `callback` will be
4329 * passed the result of the successful task. If all tasks fail, the callback
4330 * will be passed the error and result (if any) of the final attempt.
4331 *
4332 * @name tryEach
4333 * @static
4334 * @memberOf module:ControlFlow
4335 * @method
4336 * @category Control Flow
4337 * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing functions to
4338 * run, each function is passed a `callback(err, result)` it must call on
4339 * completion with an error `err` (which can be `null`) and an optional `result`
4340 * value.
4341 * @param {Function} [callback] - An optional callback which is called when one
4342 * of the tasks has succeeded, or all have failed. It receives the `err` and
4343 * `result` arguments of the last attempt at completing the `task`. Invoked with
4344 * (err, results).
4345 * @returns {Promise} a promise, if no callback is passed
4346 * @example
4347 * async.tryEach([
4348 * function getDataFromFirstWebsite(callback) {
4349 * // Try getting the data from the first website
4350 * callback(err, data);
4351 * },
4352 * function getDataFromSecondWebsite(callback) {
4353 * // First website failed,
4354 * // Try getting the data from the backup website
4355 * callback(err, data);
4356 * }
4357 * ],
4358 * // optional callback
4359 * function(err, results) {
4360 * Now do something with the data.
4361 * });
4362 *
4363 */
4364function tryEach(tasks, callback) {
4365 var error = null;
4366 var result;
4367 return eachSeries$1(tasks, (task, taskCb) => {
4368 wrapAsync(task)((err, ...args) => {
4369 if (err === false) return taskCb(err);
4370
4371 if (args.length < 2) {
4372 [result] = args;
4373 } else {
4374 result = args;
4375 }
4376 error = err;
4377 taskCb(err ? null : {});
4378 });
4379 }, () => callback(error, result));
4380}
4381
4382var tryEach$1 = awaitify(tryEach);
4383
4384/**
4385 * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original,
4386 * unmemoized form. Handy for testing.
4387 *
4388 * @name unmemoize
4389 * @static
4390 * @memberOf module:Utils
4391 * @method
4392 * @see [async.memoize]{@link module:Utils.memoize}
4393 * @category Util
4394 * @param {AsyncFunction} fn - the memoized function
4395 * @returns {AsyncFunction} a function that calls the original unmemoized function
4396 */
4397function unmemoize(fn) {
4398 return (...args) => {
4399 return (fn.unmemoized || fn)(...args);
4400 };
4401}
4402
4403/**
4404 * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when
4405 * stopped, or an error occurs.
4406 *
4407 * @name whilst
4408 * @static
4409 * @memberOf module:ControlFlow
4410 * @method
4411 * @category Control Flow
4412 * @param {AsyncFunction} test - asynchronous truth test to perform before each
4413 * execution of `iteratee`. Invoked with ().
4414 * @param {AsyncFunction} iteratee - An async function which is called each time
4415 * `test` passes. Invoked with (callback).
4416 * @param {Function} [callback] - A callback which is called after the test
4417 * function has failed and repeated execution of `iteratee` has stopped. `callback`
4418 * will be passed an error and any arguments passed to the final `iteratee`'s
4419 * callback. Invoked with (err, [results]);
4420 * @returns {Promise} a promise, if no callback is passed
4421 * @example
4422 *
4423 * var count = 0;
4424 * async.whilst(
4425 * function test(cb) { cb(null, count < 5); },
4426 * function iter(callback) {
4427 * count++;
4428 * setTimeout(function() {
4429 * callback(null, count);
4430 * }, 1000);
4431 * },
4432 * function (err, n) {
4433 * // 5 seconds have passed, n = 5
4434 * }
4435 * );
4436 */
4437function whilst(test, iteratee, callback) {
4438 callback = onlyOnce(callback);
4439 var _fn = wrapAsync(iteratee);
4440 var _test = wrapAsync(test);
4441 var results = [];
4442
4443 function next(err, ...rest) {
4444 if (err) return callback(err);
4445 results = rest;
4446 if (err === false) return;
4447 _test(check);
4448 }
4449
4450 function check(err, truth) {
4451 if (err) return callback(err);
4452 if (err === false) return;
4453 if (!truth) return callback(null, ...results);
4454 _fn(next);
4455 }
4456
4457 return _test(check);
4458}
4459var whilst$1 = awaitify(whilst, 3);
4460
4461/**
4462 * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when
4463 * stopped, or an error occurs. `callback` will be passed an error and any
4464 * arguments passed to the final `iteratee`'s callback.
4465 *
4466 * The inverse of [whilst]{@link module:ControlFlow.whilst}.
4467 *
4468 * @name until
4469 * @static
4470 * @memberOf module:ControlFlow
4471 * @method
4472 * @see [async.whilst]{@link module:ControlFlow.whilst}
4473 * @category Control Flow
4474 * @param {AsyncFunction} test - asynchronous truth test to perform before each
4475 * execution of `iteratee`. Invoked with (callback).
4476 * @param {AsyncFunction} iteratee - An async function which is called each time
4477 * `test` fails. Invoked with (callback).
4478 * @param {Function} [callback] - A callback which is called after the test
4479 * function has passed and repeated execution of `iteratee` has stopped. `callback`
4480 * will be passed an error and any arguments passed to the final `iteratee`'s
4481 * callback. Invoked with (err, [results]);
4482 * @returns {Promise} a promise, if a callback is not passed
4483 *
4484 * @example
4485 * const results = []
4486 * let finished = false
4487 * async.until(function test(page, cb) {
4488 * cb(null, finished)
4489 * }, function iter(next) {
4490 * fetchPage(url, (err, body) => {
4491 * if (err) return next(err)
4492 * results = results.concat(body.objects)
4493 * finished = !!body.next
4494 * next(err)
4495 * })
4496 * }, function done (err) {
4497 * // all pages have been fetched
4498 * })
4499 */
4500function until(test, iteratee, callback) {
4501 const _test = wrapAsync(test);
4502 return whilst$1((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback);
4503}
4504
4505/**
4506 * Runs the `tasks` array of functions in series, each passing their results to
4507 * the next in the array. However, if any of the `tasks` pass an error to their
4508 * own callback, the next function is not executed, and the main `callback` is
4509 * immediately called with the error.
4510 *
4511 * @name waterfall
4512 * @static
4513 * @memberOf module:ControlFlow
4514 * @method
4515 * @category Control Flow
4516 * @param {Array} tasks - An array of [async functions]{@link AsyncFunction}
4517 * to run.
4518 * Each function should complete with any number of `result` values.
4519 * The `result` values will be passed as arguments, in order, to the next task.
4520 * @param {Function} [callback] - An optional callback to run once all the
4521 * functions have completed. This will be passed the results of the last task's
4522 * callback. Invoked with (err, [results]).
4523 * @returns undefined
4524 * @example
4525 *
4526 * async.waterfall([
4527 * function(callback) {
4528 * callback(null, 'one', 'two');
4529 * },
4530 * function(arg1, arg2, callback) {
4531 * // arg1 now equals 'one' and arg2 now equals 'two'
4532 * callback(null, 'three');
4533 * },
4534 * function(arg1, callback) {
4535 * // arg1 now equals 'three'
4536 * callback(null, 'done');
4537 * }
4538 * ], function (err, result) {
4539 * // result now equals 'done'
4540 * });
4541 *
4542 * // Or, with named functions:
4543 * async.waterfall([
4544 * myFirstFunction,
4545 * mySecondFunction,
4546 * myLastFunction,
4547 * ], function (err, result) {
4548 * // result now equals 'done'
4549 * });
4550 * function myFirstFunction(callback) {
4551 * callback(null, 'one', 'two');
4552 * }
4553 * function mySecondFunction(arg1, arg2, callback) {
4554 * // arg1 now equals 'one' and arg2 now equals 'two'
4555 * callback(null, 'three');
4556 * }
4557 * function myLastFunction(arg1, callback) {
4558 * // arg1 now equals 'three'
4559 * callback(null, 'done');
4560 * }
4561 */
4562function waterfall (tasks, callback) {
4563 callback = once(callback);
4564 if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions'));
4565 if (!tasks.length) return callback();
4566 var taskIndex = 0;
4567
4568 function nextTask(args) {
4569 var task = wrapAsync(tasks[taskIndex++]);
4570 task(...args, onlyOnce(next));
4571 }
4572
4573 function next(err, ...args) {
4574 if (err === false) return
4575 if (err || taskIndex === tasks.length) {
4576 return callback(err, ...args);
4577 }
4578 nextTask(args);
4579 }
4580
4581 nextTask([]);
4582}
4583
4584var waterfall$1 = awaitify(waterfall);
4585
4586/**
4587 * An "async function" in the context of Async is an asynchronous function with
4588 * a variable number of parameters, with the final parameter being a callback.
4589 * (`function (arg1, arg2, ..., callback) {}`)
4590 * The final callback is of the form `callback(err, results...)`, which must be
4591 * called once the function is completed. The callback should be called with a
4592 * Error as its first argument to signal that an error occurred.
4593 * Otherwise, if no error occurred, it should be called with `null` as the first
4594 * argument, and any additional `result` arguments that may apply, to signal
4595 * successful completion.
4596 * The callback must be called exactly once, ideally on a later tick of the
4597 * JavaScript event loop.
4598 *
4599 * This type of function is also referred to as a "Node-style async function",
4600 * or a "continuation passing-style function" (CPS). Most of the methods of this
4601 * library are themselves CPS/Node-style async functions, or functions that
4602 * return CPS/Node-style async functions.
4603 *
4604 * Wherever we accept a Node-style async function, we also directly accept an
4605 * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}.
4606 * In this case, the `async` function will not be passed a final callback
4607 * argument, and any thrown error will be used as the `err` argument of the
4608 * implicit callback, and the return value will be used as the `result` value.
4609 * (i.e. a `rejected` of the returned Promise becomes the `err` callback
4610 * argument, and a `resolved` value becomes the `result`.)
4611 *
4612 * Note, due to JavaScript limitations, we can only detect native `async`
4613 * functions and not transpilied implementations.
4614 * Your environment must have `async`/`await` support for this to work.
4615 * (e.g. Node > v7.6, or a recent version of a modern browser).
4616 * If you are using `async` functions through a transpiler (e.g. Babel), you
4617 * must still wrap the function with [asyncify]{@link module:Utils.asyncify},
4618 * because the `async function` will be compiled to an ordinary function that
4619 * returns a promise.
4620 *
4621 * @typedef {Function} AsyncFunction
4622 * @static
4623 */
4624
4625var index = {
4626 apply,
4627 applyEach: applyEach$1,
4628 applyEachSeries,
4629 asyncify,
4630 auto,
4631 autoInject,
4632 cargo,
4633 cargoQueue: cargo$1,
4634 compose,
4635 concat: concat$1,
4636 concatLimit: concatLimit$1,
4637 concatSeries: concatSeries$1,
4638 constant,
4639 detect: detect$1,
4640 detectLimit: detectLimit$1,
4641 detectSeries: detectSeries$1,
4642 dir,
4643 doUntil,
4644 doWhilst: doWhilst$1,
4645 each,
4646 eachLimit: eachLimit$2,
4647 eachOf: eachOf$1,
4648 eachOfLimit: eachOfLimit$2,
4649 eachOfSeries: eachOfSeries$1,
4650 eachSeries: eachSeries$1,
4651 ensureAsync,
4652 every: every$1,
4653 everyLimit: everyLimit$1,
4654 everySeries: everySeries$1,
4655 filter: filter$1,
4656 filterLimit: filterLimit$1,
4657 filterSeries: filterSeries$1,
4658 forever: forever$1,
4659 groupBy,
4660 groupByLimit: groupByLimit$1,
4661 groupBySeries,
4662 log,
4663 map: map$1,
4664 mapLimit: mapLimit$1,
4665 mapSeries: mapSeries$1,
4666 mapValues,
4667 mapValuesLimit: mapValuesLimit$1,
4668 mapValuesSeries,
4669 memoize,
4670 nextTick,
4671 parallel,
4672 parallelLimit,
4673 priorityQueue,
4674 queue: queue$1,
4675 race: race$1,
4676 reduce: reduce$1,
4677 reduceRight,
4678 reflect,
4679 reflectAll,
4680 reject: reject$2,
4681 rejectLimit: rejectLimit$1,
4682 rejectSeries: rejectSeries$1,
4683 retry,
4684 retryable,
4685 seq,
4686 series,
4687 setImmediate: setImmediate$1,
4688 some: some$1,
4689 someLimit: someLimit$1,
4690 someSeries: someSeries$1,
4691 sortBy: sortBy$1,
4692 timeout,
4693 times,
4694 timesLimit,
4695 timesSeries,
4696 transform,
4697 tryEach: tryEach$1,
4698 unmemoize,
4699 until,
4700 waterfall: waterfall$1,
4701 whilst: whilst$1,
4702
4703 // aliases
4704 all: every$1,
4705 allLimit: everyLimit$1,
4706 allSeries: everySeries$1,
4707 any: some$1,
4708 anyLimit: someLimit$1,
4709 anySeries: someSeries$1,
4710 find: detect$1,
4711 findLimit: detectLimit$1,
4712 findSeries: detectSeries$1,
4713 flatMap: concat$1,
4714 flatMapLimit: concatLimit$1,
4715 flatMapSeries: concatSeries$1,
4716 forEach: each,
4717 forEachSeries: eachSeries$1,
4718 forEachLimit: eachLimit$2,
4719 forEachOf: eachOf$1,
4720 forEachOfSeries: eachOfSeries$1,
4721 forEachOfLimit: eachOfLimit$2,
4722 inject: reduce$1,
4723 foldl: reduce$1,
4724 foldr: reduceRight,
4725 select: filter$1,
4726 selectLimit: filterLimit$1,
4727 selectSeries: filterSeries$1,
4728 wrapSync: asyncify,
4729 during: whilst$1,
4730 doDuring: doWhilst$1
4731};
4732
4733export default index;
4734export { apply, applyEach$1 as applyEach, applyEachSeries, asyncify, auto, autoInject, cargo, cargo$1 as cargoQueue, compose, concat$1 as concat, concatLimit$1 as concatLimit, concatSeries$1 as concatSeries, constant, detect$1 as detect, detectLimit$1 as detectLimit, detectSeries$1 as detectSeries, dir, doUntil, doWhilst$1 as doWhilst, each, eachLimit$2 as eachLimit, eachOf$1 as eachOf, eachOfLimit$2 as eachOfLimit, eachOfSeries$1 as eachOfSeries, eachSeries$1 as eachSeries, ensureAsync, every$1 as every, everyLimit$1 as everyLimit, everySeries$1 as everySeries, filter$1 as filter, filterLimit$1 as filterLimit, filterSeries$1 as filterSeries, forever$1 as forever, groupBy, groupByLimit$1 as groupByLimit, groupBySeries, log, map$1 as map, mapLimit$1 as mapLimit, mapSeries$1 as mapSeries, mapValues, mapValuesLimit$1 as mapValuesLimit, mapValuesSeries, memoize, nextTick, parallel, parallelLimit, priorityQueue, queue$1 as queue, race$1 as race, reduce$1 as reduce, reduceRight, reflect, reflectAll, reject$2 as reject, rejectLimit$1 as rejectLimit, rejectSeries$1 as rejectSeries, retry, retryable, seq, series, setImmediate$1 as setImmediate, some$1 as some, someLimit$1 as someLimit, someSeries$1 as someSeries, sortBy$1 as sortBy, timeout, times, timesLimit, timesSeries, transform, tryEach$1 as tryEach, unmemoize, until, waterfall$1 as waterfall, whilst$1 as whilst, every$1 as all, everyLimit$1 as allLimit, everySeries$1 as allSeries, some$1 as any, someLimit$1 as anyLimit, someSeries$1 as anySeries, detect$1 as find, detectLimit$1 as findLimit, detectSeries$1 as findSeries, concat$1 as flatMap, concatLimit$1 as flatMapLimit, concatSeries$1 as flatMapSeries, each as forEach, eachSeries$1 as forEachSeries, eachLimit$2 as forEachLimit, eachOf$1 as forEachOf, eachOfSeries$1 as forEachOfSeries, eachOfLimit$2 as forEachOfLimit, reduce$1 as inject, reduce$1 as foldl, reduceRight as foldr, filter$1 as select, filterLimit$1 as selectLimit, filterSeries$1 as selectSeries, asyncify as wrapSync, whilst$1 as during, doWhilst$1 as doDuring };