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