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