diff options
author | Hubert Argasinski <argasinski.hubert@gmail.com> | 2016-03-31 02:22:16 -0700 |
---|---|---|
committer | Graeme Yeates <yeatesgraeme@gmail.com> | 2016-04-12 18:46:28 -0400 |
commit | 8eb2a7cec2c62edf35d7b812765bd64e6b7d484f (patch) | |
tree | 76a0c7715c612acddd9e6801dc14ec43f768176f | |
parent | a778ee63788d533111ff63b611cc5034e18a907f (diff) | |
download | async-8eb2a7cec2c62edf35d7b812765bd64e6b7d484f.tar.gz |
jsdoc-style documentation began documenting `Control Flow` methods
remaining `Control Flow` methods to document:
- queue
- priorityQueue
- cargo
- auto
- autoInject
- retry
- retryable
- iterator
- times, timesSeries, timesLimit
- race
-rw-r--r-- | lib/applyEach.js | 30 | ||||
-rw-r--r-- | lib/applyEachSeries.js | 18 | ||||
-rw-r--r-- | lib/compose.js | 32 | ||||
-rw-r--r-- | lib/doDuring.js | 20 | ||||
-rw-r--r-- | lib/doUntil.js | 19 | ||||
-rw-r--r-- | lib/doWhilst.js | 21 | ||||
-rw-r--r-- | lib/during.js | 37 | ||||
-rw-r--r-- | lib/forever.js | 28 | ||||
-rw-r--r-- | lib/parallel.js | 65 | ||||
-rw-r--r-- | lib/parallelLimit.js | 19 | ||||
-rw-r--r-- | lib/seq.js | 36 | ||||
-rw-r--r-- | lib/series.js | 63 | ||||
-rw-r--r-- | lib/until.js | 22 | ||||
-rw-r--r-- | lib/waterfall.js | 55 | ||||
-rw-r--r-- | lib/whilst.js | 33 |
15 files changed, 498 insertions, 0 deletions
diff --git a/lib/applyEach.js b/lib/applyEach.js index 73a89d2..d807e04 100644 --- a/lib/applyEach.js +++ b/lib/applyEach.js @@ -3,4 +3,34 @@ import applyEach from './internal/applyEach'; import map from './map'; +/** + * Applies the provided arguments to each function in the array, calling + * `callback` after all functions have completed. If you only provide the first + * argument, then it will return a function which lets you pass in the + * arguments as if it were a single function call. + * + * @name applyEach + * @static + * @memberOf async + * @category Control Flow + * @param {Array|Object} fns - A collection of asynchronous functions to all + * call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {Function} - If only the first argument is provided, it will return + * a function which lets you pass in the arguments as if it were a single + * function call. + * @example + * + * async.applyEach([enableSearch, updateSchema], 'bucket', callback); + * + * // partial application example: + * async.each( + * buckets, + * async.applyEach([enableSearch, updateSchema]), + * callback + * ); + */ export default applyEach(map); diff --git a/lib/applyEachSeries.js b/lib/applyEachSeries.js index 3de977f..c56989b 100644 --- a/lib/applyEachSeries.js +++ b/lib/applyEachSeries.js @@ -3,4 +3,22 @@ import applyEach from './internal/applyEach'; import mapSeries from './mapSeries'; +/** + * The same as `applyEach` but runs only a single async operation at a time. + * + * @name applyEachSeries + * @static + * @memberOf async + * @see `async.applyEach` + * @category Control Flow + * @param {Array|Object} fns - A collection of asynchronous functions to all + * call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {Function} - If only the first argument is provided, it will return + * a function which lets you pass in the arguments as if it were a single + * function call. + */ export default applyEach(mapSeries); diff --git a/lib/compose.js b/lib/compose.js index 9e92521..9c954d0 100644 --- a/lib/compose.js +++ b/lib/compose.js @@ -4,6 +4,38 @@ import seq from './seq'; var reverse = Array.prototype.reverse; +/** + * Creates a function which is a composition of the passed asynchronous + * functions. Each function consumes the return value of the function that + * follows. Composing functions `f()`, `g()`, and `h()` would produce the result + * of `f(g(h()))`, only this version uses callbacks to obtain the return values. + * + * Each function is executed with the `this` binding of the composed function. + * + * @name compose + * @static + * @memberOf async + * @category Control Flow + * @param {...Function} functions - the asynchronous functions to compose + * @example + * + * function add1(n, callback) { + * setTimeout(function () { + * callback(null, n + 1); + * }, 10); + * } + * + * function mul3(n, callback) { + * setTimeout(function () { + * callback(null, n * 3); + * }, 10); + * } + * + * var add1mul3 = async.compose(mul3, add1); + * add1mul3(4, function (err, result) { + * // result now equals 15 + * }); + */ export default function compose(/* functions... */) { return seq.apply(null, reverse.call(arguments)); } diff --git a/lib/doDuring.js b/lib/doDuring.js index 73504c2..6833a78 100644 --- a/lib/doDuring.js +++ b/lib/doDuring.js @@ -2,6 +2,26 @@ import during from './during'; +/** + * The post-check version of [`during`](#during). To reflect the difference in + * the order of operations, the arguments `test` and `fn` are switched. + * + * Also a version of [`doWhilst`](#doWhilst) with asynchronous `test` function. + * @name doDuring + * @static + * @memberOf async + * @see `async.during` + * @category Control Flow + * @param {Function} fn - A function which is called each time `test` passes. + * The function is passed a `callback(err)`, which must be called once it has + * completed with an optional `err` argument. Invoked with (callback). + * @param {Function} test - asynchronous truth test to perform before each + * execution of `fn`. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `fn` has stopped. `callback` + * will be passed an error and any arguments passed to the final `fn`'s + * callback. Invoked with (err, [results]); + */ export default function doDuring(iteratee, test, cb) { var calls = 0; diff --git a/lib/doUntil.js b/lib/doUntil.js index d5f2b83..e5c48c9 100644 --- a/lib/doUntil.js +++ b/lib/doUntil.js @@ -2,6 +2,25 @@ import doWhilst from './doWhilst'; +/** + * Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the + * argument ordering differs from `until`. + * + * @name doUntil + * @static + * @memberOf async + * @see `async.doWhilst` + * @category Control Flow + * @param {Function} fn - A function which is called each time `test` fails. + * The function is passed a `callback(err)`, which must be called once it has + * completed with an optional `err` argument. Invoked with (callback). + * @param {Function} test - synchronous truth test to perform before each + * execution of `fn`. Invoked with (). + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `fn` has stopped. `callback` + * will be passed an error and any arguments passed to the final `fn`'s + * callback. Invoked with (err, [results]); + */ export default function doUntil(iteratee, test, cb) { return doWhilst(iteratee, function() { return !test.apply(this, arguments); diff --git a/lib/doWhilst.js b/lib/doWhilst.js index 1cd56a7..54c8303 100644 --- a/lib/doWhilst.js +++ b/lib/doWhilst.js @@ -2,6 +2,27 @@ import whilst from './whilst'; +/** + * The post-check version of [`whilst`](#whilst). To reflect the difference in + * the order of operations, the arguments `test` and `fn` are switched. + * + * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + * + * @name doWhilst + * @static + * @memberOf async + * @see `async.whilst` + * @category Control Flow + * @param {Function} fn - A function which is called each time `test` passes. + * The function is passed a `callback(err)`, which must be called once it has + * completed with an optional `err` argument. Invoked with (callback). + * @param {Function} test - synchronous truth test to perform before each + * execution of `fn`. Invoked with (). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `fn` has stopped. `callback` + * will be passed an error and any arguments passed to the final `fn`'s + * callback. Invoked with (err, [results]); + */ export default function doWhilst(iteratee, test, cb) { var calls = 0; return whilst(function() { diff --git a/lib/during.js b/lib/during.js index 013a3dc..7c3d10c 100644 --- a/lib/during.js +++ b/lib/during.js @@ -3,6 +3,43 @@ import noop from 'lodash/noop'; import rest from 'lodash/rest'; +/** + * Like [`whilst`](#whilst), except the `test` is an asynchronous function that + * is passed a callback in the form of `function (err, truth)`. If error is + * passed to `test` or `fn`, the main callback is immediately called with the + * value of the error. + * + * @name during + * @static + * @memberOf async + * @see `async.whilst` + * @category Control Flow + * @param {Function} test - asynchronous truth test to perform before each + * execution of `fn`. Invoked with (callback). + * @param {Function} fn - A function which is called each time `test` passes. + * The function is passed a `callback(err)`, which must be called once it has + * completed with an optional `err` argument. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `fn` has stopped. `callback` + * will be passed an error and any arguments passed to the final `fn`'s + * callback. Invoked with (err, [results]); + * @example + * + * var count = 0; + * + * async.during( + * function (callback) { + * return callback(null, count < 5); + * }, + * function (callback) { + * count++; + * setTimeout(callback, 1000); + * }, + * function (err) { + * // 5 seconds have passed + * } + * ); + */ export default function during(test, iteratee, cb) { cb = cb || noop; diff --git a/lib/forever.js b/lib/forever.js index 82d004a..23f261b 100644 --- a/lib/forever.js +++ b/lib/forever.js @@ -5,6 +5,34 @@ import noop from 'lodash/noop'; import onlyOnce from './internal/onlyOnce'; import ensureAsync from './ensureAsync'; +/** + * Calls the asynchronous function `fn` with a callback parameter that allows it + * to call itself again, in series, indefinitely. + + * If an error is passed to the + * callback then `errback` is called with the error, and execution stops, + * otherwise it will never be called. + * + * @name forever + * @static + * @memberOf async + * @category Control Flow + * @param {Function} fn - a function to call repeatedly. Invoked with (next). + * @param {Function} [errback] - when `fn` passes an error to it's callback, + * this function will be called, and execution stops. Invoked with (err). + * @example + * + * async.forever( + * function(next) { + * // next is suitable for passing to things that need a callback(err [, whatever]); + * // it will result in this function being called again. + * }, + * function(err) { + * // if next is called with a value in its first parameter, it will appear + * // in here as 'err', and execution will stop. + * } + * ); + */ export default function forever(fn, cb) { var done = onlyOnce(cb || noop); var task = ensureAsync(fn); diff --git a/lib/parallel.js b/lib/parallel.js index 6114d6a..8856fb1 100644 --- a/lib/parallel.js +++ b/lib/parallel.js @@ -3,4 +3,69 @@ import parallelLimit from './parallelLimit'; import doLimit from './internal/doLimit'; +/** + * Run the `tasks` collection of functions in parallel, without waiting until + * the previous function has completed. If any of the functions pass an error to + * its callback, the main `callback` is immediately called with the value of the + * error. Once the `tasks` have completed, the results are passed to the final + * `callback` as an array. + * + * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about + * parallel execution of code. If your tasks do not use any timers or perform + * any I/O, they will actually be executed in series. Any synchronous setup + * sections for each task will happen one after the other. JavaScript remains + * single-threaded. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from [`parallel`](#parallel). + * + * @name parallel + * @static + * @memberOf async + * @category Control Flow + * @param {Array|Object} tasks - A collection containing functions to run. + * Each function is passed a `callback(err, result)` which it must call on + * completion with an error `err` (which can be `null`) and an optional `result` + * value. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + * @example + * async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ], + * // optional callback + * function(err, results) { + * // the results array will equal ['one','two'] even though + * // the second function had a shorter timeout. + * }); + * + * // an example using an object instead of an array + * async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * // results is now equals to: {one: 1, two: 2} + * }); + */ export default doLimit(parallelLimit, Infinity); diff --git a/lib/parallelLimit.js b/lib/parallelLimit.js index 7e66bed..188624c 100644 --- a/lib/parallelLimit.js +++ b/lib/parallelLimit.js @@ -3,6 +3,25 @@ import eachOfLimit from './internal/eachOfLimit'; import parallel from './internal/parallel'; +/** + * The same as `parallel` but runs a maximum of `limit` async operations at a + * time. + * + * @name parallel + * @static + * @memberOf async + * @see `async.parallel` + * @category Control Flow + * @param {Array|Collection} tasks - A collection containing functions to run. + * Each function is passed a `callback(err, result)` which it must call on + * completion with an error `err` (which can be `null`) and an optional `result` + * value. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + */ export default function parallelLimit(tasks, limit, cb) { return parallel(eachOfLimit(limit), tasks, cb); } @@ -4,6 +4,42 @@ import noop from 'lodash/noop'; import rest from 'lodash/rest'; import reduce from './reduce'; +/** + * Version of the compose function that is more natural to read. Each function + * consumes the return value of the previous function. It is the equivalent of + * [`compose`](#compose) with the arguments reversed. + * + * Each function is executed with the `this` binding of the composed function. + * + * @name seq + * @static + * @memberOf async + * @see `async.compose` + * @category Control Flow + * @param {...Function} functions - the asynchronous functions to compose + * @example + * + * // Requires lodash (or underscore), express3 and dresende's orm2. + * // Part of an app, that fetches cats of the logged user. + * // This example uses `seq` function to avoid overnesting and error + * // handling clutter. + * app.get('/cats', function(request, response) { + * var User = request.models.User; + * async.seq( + * _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data)) + * function(user, fn) { + * user.getCats(fn); // 'getCats' has signature (callback(err, data)) + * } + * )(req.session.user_id, function (err, cats) { + * if (err) { + * console.error(err); + * response.json({ status: 'error', message: err.message }); + * } else { + * response.json({ status: 'ok', message: 'Cats found', data: cats }); + * } + * }); + * }); + */ export default function seq( /* functions... */ ) { var fns = arguments; return rest(function(args) { diff --git a/lib/series.js b/lib/series.js index bd8e15d..b0cc6bf 100644 --- a/lib/series.js +++ b/lib/series.js @@ -3,6 +3,69 @@ import parallel from './internal/parallel'; import eachOfSeries from './eachOfSeries'; +/** + * Run the functions in the `tasks` collection in series, each one running once + * the previous function has completed. If any functions in the series pass an + * error to its callback, no more functions are run, and `callback` is + * immediately called with the value of the error. Otherwise, `callback` + * receives an array of results when `tasks` have completed. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function, and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from [`series`](#series). + * + * **Note** that while many implementations preserve the order of object + * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) + * explicitly states that + * + * > The mechanics and order of enumerating the properties is not specified. + * + * So if you rely on the order in which your series of functions are executed, + * and want this to work on all platforms, consider using an array. + * + * @name series + * @static + * @memberOf async + * @category Control Flow + * @param {Array|Object} tasks - A collection containing functions to run, each + * function is passed a `callback(err, result)` it must call on completion with + * an error `err` (which can be `null`) and an optional `result` value. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This function gets a results array (or object) + * containing all the result arguments passed to the `task` callbacks. Invoked + * with (err, result). + * @example + * async.series([ + * function(callback) { + * // do some stuff ... + * callback(null, 'one'); + * }, + * function(callback) { + * // do some more stuff ... + * callback(null, 'two'); + * } + * ], + * // optional callback + * function(err, results) { + * // results is now equal to ['one', 'two'] + * }); + * + * async.series({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback){ + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * // results is now equal to: {one: 1, two: 2} + * }); + */ export default function series(tasks, cb) { return parallel(eachOfSeries, tasks, cb); } diff --git a/lib/until.js b/lib/until.js index b1283f2..0c5a1aa 100644 --- a/lib/until.js +++ b/lib/until.js @@ -2,6 +2,28 @@ import whilst from './whilst'; +/** + * Repeatedly call `fn` until `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. `callback` will be passed an error and any + * arguments passed to the final `fn`'s callback. + * + * The inverse of [`whilst`](#whilst). + * + * @name until + * @static + * @memberOf async + * @see `async.whilst` + * @category Control Flow + * @param {Function} test - synchronous truth test to perform before each + * execution of `fn`. Invoked with (). + * @param {Function} fn - A function which is called each time `test` fails. + * The function is passed a `callback(err)`, which must be called once it has + * completed with an optional `err` argument. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `fn` has stopped. `callback` + * will be passed an error and any arguments passed to the final `fn`'s + * callback. Invoked with (err, [results]); + */ export default function until(test, iteratee, cb) { return whilst(function() { return !test.apply(this, arguments); diff --git a/lib/waterfall.js b/lib/waterfall.js index aaed2ee..c76b332 100644 --- a/lib/waterfall.js +++ b/lib/waterfall.js @@ -7,6 +7,61 @@ import rest from 'lodash/rest'; import onlyOnce from './internal/onlyOnce'; +/** + * Runs the `tasks` array of functions in series, each passing their results to + * the next in the array. However, if any of the `tasks` pass an error to their + * own callback, the next function is not executed, and the main `callback` is + * immediately called with the error. + * + * @name waterfall + * @static + * @memberOf async + * @category Control Flow + * @param {Array} tasks - An array of functions to run, each function is passed + * a `callback(err, result1, result2, ...)` it must call on completion. The + * first argument is an error (which can be `null`) and any further arguments + * will be passed as arguments in order to the next task. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This will be passed the results of the last task's + * callback. Invoked with (err, [results]). + * @example + * + * async.waterfall([ + * function(callback) { + * callback(null, 'one', 'two'); + * }, + * function(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * }, + * function(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + * ], function (err, result) { + * // result now equals 'done' + * }); + * + * // Or, with named functions: + * async.waterfall([ + * myFirstFunction, + * mySecondFunction, + * myLastFunction, + * ], function (err, result) { + * // result now equals 'done' + * }); + * function myFirstFunction(callback) { + * callback(null, 'one', 'two'); + * } + * function mySecondFunction(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * } + * function myLastFunction(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + */ export default function(tasks, cb) { cb = once(cb || noop); if (!isArray(tasks)) return cb(new Error('First argument to waterfall must be an array of functions')); diff --git a/lib/whilst.js b/lib/whilst.js index 9406cd4..00c510c 100644 --- a/lib/whilst.js +++ b/lib/whilst.js @@ -3,6 +3,39 @@ import noop from 'lodash/noop'; import rest from 'lodash/rest'; +/** + * Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. + * + * @name whilst + * @static + * @memberOf async + * @category Control Flow + * @param {Function} test - synchronous truth test to perform before each + * execution of `fn`. Invoked with (). + * @param {Function} fn - A function which is called each time `test` passes. + * The function is passed a `callback(err)`, which must be called once it has + * completed with an optional `err` argument. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `fn` has stopped. `callback` + * will be passed an error and any arguments passed to the final `fn`'s + * callback. Invoked with (err, [results]); + * @example + * + * var count = 0; + * async.whilst( + * function() { return count < 5; }, + * function(callback) { + * count++; + * setTimeout(function() { + * callback(null, count); + * }, 1000); + * }, + * function (err, n) { + * // 5 seconds have passed, n = 5 + * } + * ); + */ export default function whilst(test, iteratee, cb) { cb = cb || noop; if (!test()) return cb(null); |