|
866 | 866 | /** |
867 | 867 | * Applies the provided arguments to each function in the array, calling |
868 | 868 | * `callback` after all functions have completed. If you only provide the first |
869 | | - * argument, then it will return a function which lets you pass in the |
870 | | - * arguments as if it were a single function call. |
| 869 | + * argument, `fns`, then it will return a function which lets you pass in the |
| 870 | + * arguments as if it were a single function call. If more arguments are |
| 871 | + * provided, `callback` is required while `args` is still optional. |
871 | 872 | * |
872 | 873 | * @name applyEach |
873 | 874 | * @static |
874 | 875 | * @memberOf module:ControlFlow |
875 | 876 | * @method |
876 | 877 | * @category Control Flow |
877 | | - * @param {Array|Iterable|Object} fns - A collection of asynchronous functions to all |
878 | | - * call with the same arguments |
| 878 | + * @param {Array|Iterable|Object} fns - A collection of asynchronous functions |
| 879 | + * to all call with the same arguments |
879 | 880 | * @param {...*} [args] - any number of separate arguments to pass to the |
880 | 881 | * function. |
881 | 882 | * @param {Function} [callback] - the final argument should be the callback, |
882 | 883 | * called when all functions have completed processing. |
883 | | - * @returns {Function} - If only the first argument is provided, it will return |
884 | | - * a function which lets you pass in the arguments as if it were a single |
885 | | - * function call. |
| 884 | + * @returns {Function} - If only the first argument, `fns`, is provided, it will |
| 885 | + * return a function which lets you pass in the arguments as if it were a single |
| 886 | + * function call. The signature is `(..args, callback)`. If invoked with any |
| 887 | + * arguments, `callback` is required. |
886 | 888 | * @example |
887 | 889 | * |
888 | 890 | * async.applyEach([enableSearch, updateSchema], 'bucket', callback); |
|
1984 | 1986 | q.drain(); |
1985 | 1987 | }); |
1986 | 1988 | } |
1987 | | - arrayEach(data, function (task) { |
| 1989 | + |
| 1990 | + for (var i = 0, l = data.length; i < l; i++) { |
1988 | 1991 | var item = { |
1989 | | - data: task, |
| 1992 | + data: data[i], |
1990 | 1993 | callback: callback || noop |
1991 | 1994 | }; |
1992 | 1995 |
|
|
1995 | 1998 | } else { |
1996 | 1999 | q._tasks.push(item); |
1997 | 2000 | } |
1998 | | - }); |
| 2001 | + } |
1999 | 2002 | setImmediate$1(q.process); |
2000 | 2003 | } |
2001 | 2004 |
|
2002 | 2005 | function _next(tasks) { |
2003 | 2006 | return baseRest(function (args) { |
2004 | 2007 | workers -= 1; |
2005 | 2008 |
|
2006 | | - arrayEach(tasks, function (task) { |
2007 | | - arrayEach(workersList, function (worker, index) { |
2008 | | - if (worker === task) { |
2009 | | - workersList.splice(index, 1); |
2010 | | - return false; |
2011 | | - } |
2012 | | - }); |
| 2009 | + for (var i = 0, l = tasks.length; i < l; i++) { |
| 2010 | + var task = tasks[i]; |
| 2011 | + var index = baseIndexOf(workersList, task, 0); |
| 2012 | + if (index >= 0) { |
| 2013 | + workersList.splice(index); |
| 2014 | + } |
2013 | 2015 |
|
2014 | 2016 | task.callback.apply(task, args); |
2015 | 2017 |
|
2016 | 2018 | if (args[0] != null) { |
2017 | 2019 | q.error(args[0], task.data); |
2018 | 2020 | } |
2019 | | - }); |
| 2021 | + } |
2020 | 2022 |
|
2021 | 2023 | if (workers <= q.concurrency - q.buffer) { |
2022 | 2024 | q.unsaturated(); |
|
2728 | 2730 | * passes. The function is passed a `callback(err)`, which must be called once |
2729 | 2731 | * it has completed with an optional `err` argument. Invoked with (callback). |
2730 | 2732 | * @param {Function} test - synchronous truth test to perform after each |
2731 | | - * execution of `iteratee`. Invoked with Invoked with the non-error callback |
2732 | | - * results of `iteratee`. |
| 2733 | + * execution of `iteratee`. Invoked with the non-error callback results of |
| 2734 | + * `iteratee`. |
2733 | 2735 | * @param {Function} [callback] - A callback which is called after the test |
2734 | 2736 | * function has failed and repeated execution of `iteratee` has stopped. |
2735 | 2737 | * `callback` will be passed an error and any arguments passed to the final |
|
2904 | 2906 | * @see [async.each]{@link module:Collections.each} |
2905 | 2907 | * @alias forEachLimit |
2906 | 2908 | * @category Collection |
2907 | | - * @param {Array|Iterable|Object} coll - A colleciton to iterate over. |
| 2909 | + * @param {Array|Iterable|Object} coll - A collection to iterate over. |
2908 | 2910 | * @param {number} limit - The maximum number of async operations at a time. |
2909 | 2911 | * @param {Function} iteratee - A function to apply to each item in `coll`. The |
2910 | 2912 | * iteratee is passed a `callback(err)` which must be called once it has |
|
3714 | 3716 | nextNode = nextNode.next; |
3715 | 3717 | } |
3716 | 3718 |
|
3717 | | - arrayEach(data, function (task) { |
| 3719 | + for (var i = 0, l = data.length; i < l; i++) { |
3718 | 3720 | var item = { |
3719 | | - data: task, |
| 3721 | + data: data[i], |
3720 | 3722 | priority: priority, |
3721 | 3723 | callback: callback |
3722 | 3724 | }; |
|
3726 | 3728 | } else { |
3727 | 3729 | q._tasks.push(item); |
3728 | 3730 | } |
3729 | | - }); |
| 3731 | + } |
3730 | 3732 | setImmediate$1(q.process); |
3731 | 3733 | }; |
3732 | 3734 |
|
|
3738 | 3740 |
|
3739 | 3741 | /** |
3740 | 3742 | * Runs the `tasks` array of functions in parallel, without waiting until the |
3741 | | - * previous function has completed. Once any the `tasks` completed or pass an |
| 3743 | + * previous function has completed. Once any of the `tasks` complete or pass an |
3742 | 3744 | * error to its callback, the main `callback` is immediately called. It's |
3743 | 3745 | * equivalent to `Promise.race()`. |
3744 | 3746 | * |
|
3777 | 3779 | callback = once(callback || noop); |
3778 | 3780 | if (!isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions')); |
3779 | 3781 | if (!tasks.length) return callback(); |
3780 | | - arrayEach(tasks, function (task) { |
3781 | | - task(callback); |
3782 | | - }); |
| 3782 | + for (var i = 0, l = tasks.length; i < l; i++) { |
| 3783 | + tasks[i](callback); |
| 3784 | + } |
3783 | 3785 | } |
3784 | 3786 |
|
3785 | 3787 | var slice = Array.prototype.slice; |
|
4074 | 4076 | * * `interval` - The time to wait between retries, in milliseconds. The |
4075 | 4077 | * default is `0`. The interval may also be specified as a function of the |
4076 | 4078 | * retry count (see example). |
| 4079 | + * * `errorFilter` - An optional synchronous function that is invoked on |
| 4080 | + * erroneous result. If it returns `true` the retry attempts will continue; |
| 4081 | + * if the function returns `false` the retry flow is aborted with the current |
| 4082 | + * attempt's error and result being returned to the final callback. |
| 4083 | + * Invoked with (err). |
4077 | 4084 | * * If `opts` is a number, the number specifies the number of times to retry, |
4078 | 4085 | * with the default interval of `0`. |
4079 | 4086 | * @param {Function} task - A function which receives two arguments: (1) a |
|
4117 | 4124 | * // do something with the result |
4118 | 4125 | * }); |
4119 | 4126 | * |
| 4127 | + * // try calling apiMethod only when error condition satisfies, all other |
| 4128 | + * // errors will abort the retry control flow and return to final callback |
| 4129 | + * async.retry({ |
| 4130 | + * errorFilter: function(err) { |
| 4131 | + * return err.message === 'Temporary error'; // only retry on a specific error |
| 4132 | + * } |
| 4133 | + * }, apiMethod, function(err, result) { |
| 4134 | + * // do something with the result |
| 4135 | + * }); |
| 4136 | + * |
4120 | 4137 | * // It can also be embedded within other control flow functions to retry |
4121 | 4138 | * // individual methods that are not as reliable, like this: |
4122 | 4139 | * async.auto({ |
|
4125 | 4142 | * }, function(err, results) { |
4126 | 4143 | * // do something with the results |
4127 | 4144 | * }); |
| 4145 | + * |
4128 | 4146 | */ |
4129 | 4147 | function retry(opts, task, callback) { |
4130 | 4148 | var DEFAULT_TIMES = 5; |
|
4140 | 4158 | acc.times = +t.times || DEFAULT_TIMES; |
4141 | 4159 |
|
4142 | 4160 | acc.intervalFunc = typeof t.interval === 'function' ? t.interval : constant$1(+t.interval || DEFAULT_INTERVAL); |
| 4161 | + |
| 4162 | + acc.errorFilter = t.errorFilter; |
4143 | 4163 | } else if (typeof t === 'number' || typeof t === 'string') { |
4144 | 4164 | acc.times = +t || DEFAULT_TIMES; |
4145 | 4165 | } else { |
|
4162 | 4182 | var attempt = 1; |
4163 | 4183 | function retryAttempt() { |
4164 | 4184 | task(function (err) { |
4165 | | - if (err && attempt++ < options.times) { |
| 4185 | + if (err && attempt++ < options.times && (typeof options.errorFilter != 'function' || options.errorFilter(err))) { |
4166 | 4186 | setTimeout(retryAttempt, options.intervalFunc(attempt)); |
4167 | 4187 | } else { |
4168 | 4188 | callback.apply(null, arguments); |
|
4436 | 4456 | * @param {*} [info] - Any variable you want attached (`string`, `object`, etc) |
4437 | 4457 | * to timeout Error for more information.. |
4438 | 4458 | * @returns {Function} Returns a wrapped function that can be used with any of |
4439 | | - * the control flow functions. |
| 4459 | + * the control flow functions. Invoke this function with the same |
| 4460 | + * parameters as you would `asyncFunc`. |
4440 | 4461 | * @example |
4441 | 4462 | * |
4442 | | - * async.timeout(function(callback) { |
4443 | | - * doAsyncTask(callback); |
4444 | | - * }, 1000); |
| 4463 | + * function myFunction(foo, callback) { |
| 4464 | + * doAsyncTask(foo, function(err, data) { |
| 4465 | + * // handle errors |
| 4466 | + * if (err) return callback(err); |
| 4467 | + * |
| 4468 | + * // do some stuff ... |
| 4469 | + * |
| 4470 | + * // return processed data |
| 4471 | + * return callback(null, data); |
| 4472 | + * }); |
| 4473 | + * } |
| 4474 | + * |
| 4475 | + * var wrapped = async.timeout(myFunction, 1000); |
| 4476 | + * |
| 4477 | + * // call `wrapped` as you would `myFunction` |
| 4478 | + * wrapped({ bar: 'bar' }, function(err, data) { |
| 4479 | + * // if `myFunction` takes < 1000 ms to execute, `err` |
| 4480 | + * // and `data` will have their expected values |
| 4481 | + * |
| 4482 | + * // else `err` will be an Error with the code 'ETIMEDOUT' |
| 4483 | + * }); |
4445 | 4484 | */ |
4446 | 4485 | function timeout(asyncFn, milliseconds, info) { |
4447 | 4486 | var originalCallback, timer; |
|
4649 | 4688 | } |
4650 | 4689 |
|
4651 | 4690 | /** |
4652 | | - * Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when |
| 4691 | + * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when |
4653 | 4692 | * stopped, or an error occurs. |
4654 | 4693 | * |
4655 | 4694 | * @name whilst |
|
4658 | 4697 | * @method |
4659 | 4698 | * @category Control Flow |
4660 | 4699 | * @param {Function} test - synchronous truth test to perform before each |
4661 | | - * execution of `fn`. Invoked with (). |
| 4700 | + * execution of `iteratee`. Invoked with (). |
4662 | 4701 | * @param {Function} iteratee - A function which is called each time `test` passes. |
4663 | 4702 | * The function is passed a `callback(err)`, which must be called once it has |
4664 | 4703 | * completed with an optional `err` argument. Invoked with (callback). |
4665 | 4704 | * @param {Function} [callback] - A callback which is called after the test |
4666 | | - * function has failed and repeated execution of `fn` has stopped. `callback` |
4667 | | - * will be passed an error and any arguments passed to the final `fn`'s |
| 4705 | + * function has failed and repeated execution of `iteratee` has stopped. `callback` |
| 4706 | + * will be passed an error and any arguments passed to the final `iteratee`'s |
4668 | 4707 | * callback. Invoked with (err, [results]); |
4669 | 4708 | * @returns undefined |
4670 | 4709 | * @example |
|
0 commit comments