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