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