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