|
# Async.js |
|
|
|
[](https://travis-ci.org/caolan/async) |
|
|
|
|
|
Async is a utility module which provides straight-forward, powerful functions |
|
for working with asynchronous JavaScript. Although originally designed for |
|
use with [Node.js](http://nodejs.org) and installable via `npm install async`, |
|
it can also be used directly in the browser. |
|
|
|
Async is also installable via: |
|
|
|
- [bower](http://bower.io/): `bower install async` |
|
- [component](https://github.com/component/component): `component install |
|
caolan/async` |
|
- [jam](http://jamjs.org/): `jam install async` |
|
- [spm](http://spmjs.io/): `spm install async` |
|
|
|
Async provides around 20 functions that include the usual 'functional' |
|
suspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns |
|
for asynchronous control flow (`parallel`, `series`, `waterfall`…). All these |
|
functions assume you follow the Node.js convention of providing a single |
|
callback as the last argument of your `async` function. |
|
|
|
|
|
## Quick Examples |
|
|
|
```javascript |
|
async.map(['file1','file2','file3'], fs.stat, function(err, results){ |
|
// results is now an array of stats for each file |
|
}); |
|
|
|
async.filter(['file1','file2','file3'], fs.exists, function(results){ |
|
// results now equals an array of the existing files |
|
}); |
|
|
|
async.parallel([ |
|
function(){ ... }, |
|
function(){ ... } |
|
], callback); |
|
|
|
async.series([ |
|
function(){ ... }, |
|
function(){ ... } |
|
]); |
|
``` |
|
|
|
There are many more functions available so take a look at the docs below for a |
|
full list. This module aims to be comprehensive, so if you feel anything is |
|
missing please create a GitHub issue for it. |
|
|
|
## Common Pitfalls |
|
|
|
### Binding a context to an iterator |
|
|
|
This section is really about `bind`, not about `async`. If you are wondering how to |
|
make `async` execute your iterators in a given context, or are confused as to why |
|
a method of another library isn't working as an iterator, study this example: |
|
|
|
```js |
|
// Here is a simple object with an (unnecessarily roundabout) squaring method |
|
var AsyncSquaringLibrary = { |
|
squareExponent: 2, |
|
square: function(number, callback){ |
|
var result = Math.pow(number, this.squareExponent); |
|
setTimeout(function(){ |
|
callback(null, result); |
|
}, 200); |
|
} |
|
}; |
|
|
|
async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ |
|
// result is [NaN, NaN, NaN] |
|
// This fails because the `this.squareExponent` expression in the square |
|
// function is not evaluated in the context of AsyncSquaringLibrary, and is |
|
// therefore undefined. |
|
}); |
|
|
|
async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ |
|
// result is [1, 4, 9] |
|
// With the help of bind we can attach a context to the iterator before |
|
// passing it to async. Now the square function will be executed in its |
|
// 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` |
|
// will be as expected. |
|
}); |
|
``` |
|
|
|
## Download |
|
|
|
The source is available for download from |
|
[GitHub](http://github.com/caolan/async). |
|
Alternatively, you can install using Node Package Manager (`npm`): |
|
|
|
npm install async |
|
|
|
__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed |
|
|
|
## In the Browser |
|
|
|
So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. |
|
|
|
Usage: |
|
|
|
```html |
|
<script type="text/javascript" src="async.js"></script> |
|
<script type="text/javascript"> |
|
|
|
async.map(data, asyncProcess, function(err, results){ |
|
alert(results); |
|
}); |
|
|
|
</script> |
|
``` |
|
|
|
## Documentation |
|
|
|
### Collections |
|
|
|
* [`each`](#each) |
|
* [`eachSeries`](#eachSeries) |
|
* [`eachLimit`](#eachLimit) |
|
* [`map`](#map) |
|
* [`mapSeries`](#mapSeries) |
|
* [`mapLimit`](#mapLimit) |
|
* [`filter`](#filter) |
|
* [`filterSeries`](#filterSeries) |
|
* [`reject`](#reject) |
|
* [`rejectSeries`](#rejectSeries) |
|
* [`reduce`](#reduce) |
|
* [`reduceRight`](#reduceRight) |
|
* [`detect`](#detect) |
|
* [`detectSeries`](#detectSeries) |
|
* [`sortBy`](#sortBy) |
|
* [`some`](#some) |
|
* [`every`](#every) |
|
* [`concat`](#concat) |
|
* [`concatSeries`](#concatSeries) |
|
|
|
### Control Flow |
|
|
|
* [`series`](#seriestasks-callback) |
|
* [`parallel`](#parallel) |
|
* [`parallelLimit`](#parallellimittasks-limit-callback) |
|
* [`whilst`](#whilst) |
|
* [`doWhilst`](#doWhilst) |
|
* [`until`](#until) |
|
* [`doUntil`](#doUntil) |
|
* [`forever`](#forever) |
|
* [`waterfall`](#waterfall) |
|
* [`compose`](#compose) |
|
* [`seq`](#seq) |
|
* [`applyEach`](#applyEach) |
|
* [`applyEachSeries`](#applyEachSeries) |
|
* [`queue`](#queue) |
|
* [`priorityQueue`](#priorityQueue) |
|
* [`cargo`](#cargo) |
|
* [`auto`](#auto) |
|
* [`retry`](#retry) |
|
* [`iterator`](#iterator) |
|
* [`apply`](#apply) |
|
* [`nextTick`](#nextTick) |
|
* [`times`](#times) |
|
* [`timesSeries`](#timesSeries) |
|
|
|
### Utils |
|
|
|
* [`memoize`](#memoize) |
|
* [`unmemoize`](#unmemoize) |
|
* [`log`](#log) |
|
* [`dir`](#dir) |
|
* [`noConflict`](#noConflict) |
|
|
|
|
|
## Collections |
|
|
|
<a name="forEach" /> |
|
<a name="each" /> |
|
### each(arr, iterator, callback) |
|
|
|
Applies the function `iterator` to each item in `arr`, in parallel. |
|
The `iterator` is called with an item from the list, and a callback for when it |
|
has finished. If the `iterator` passes an error to its `callback`, the main |
|
`callback` (for the `each` function) is immediately called with the error. |
|
|
|
Note, that since this function applies `iterator` to each item in parallel, |
|
there is no guarantee that the iterator functions will complete in order. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A function to apply to each item in `arr`. |
|
The iterator is passed a `callback(err)` which must be called once it has |
|
completed. If no error has occurred, the `callback` should be run without |
|
arguments or with an explicit `null` argument. |
|
* `callback(err)` - A callback which is called when all `iterator` functions |
|
have finished, or an error occurs. |
|
|
|
__Examples__ |
|
|
|
|
|
```js |
|
// assuming openFiles is an array of file names and saveFile is a function |
|
// to save the modified contents of that file: |
|
|
|
async.each(openFiles, saveFile, function(err){ |
|
// if any of the saves produced an error, err would equal that error |
|
}); |
|
``` |
|
|
|
```js |
|
// assuming openFiles is an array of file names |
|
|
|
async.each(openFiles, function(file, callback) { |
|
|
|
// Perform operation on file here. |
|
console.log('Processing file ' + file); |
|
|
|
if( file.length > 32 ) { |
|
console.log('This file name is too long'); |
|
callback('File name too long'); |
|
} else { |
|
// Do work to process file here |
|
console.log('File processed'); |
|
callback(); |
|
} |
|
}, function(err){ |
|
// if any of the file processing produced an error, err would equal that error |
|
if( err ) { |
|
// One of the iterations produced an error. |
|
// All processing will now stop. |
|
console.log('A file failed to process'); |
|
} else { |
|
console.log('All files have been processed successfully'); |
|
} |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="forEachSeries" /> |
|
<a name="eachSeries" /> |
|
### eachSeries(arr, iterator, callback) |
|
|
|
The same as [`each`](#each), only `iterator` is applied to each item in `arr` in |
|
series. The next `iterator` is only called once the current one has completed. |
|
This means the `iterator` functions will complete in order. |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="forEachLimit" /> |
|
<a name="eachLimit" /> |
|
### eachLimit(arr, limit, iterator, callback) |
|
|
|
The same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously |
|
running at any time. |
|
|
|
Note that the items in `arr` are not processed in batches, so there is no guarantee that |
|
the first `limit` `iterator` functions will complete before any others are started. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `limit` - The maximum number of `iterator`s to run at any time. |
|
* `iterator(item, callback)` - A function to apply to each item in `arr`. |
|
The iterator is passed a `callback(err)` which must be called once it has |
|
completed. If no error has occurred, the callback should be run without |
|
arguments or with an explicit `null` argument. |
|
* `callback(err)` - A callback which is called when all `iterator` functions |
|
have finished, or an error occurs. |
|
|
|
__Example__ |
|
|
|
```js |
|
// Assume documents is an array of JSON objects and requestApi is a |
|
// function that interacts with a rate-limited REST api. |
|
|
|
async.eachLimit(documents, 20, requestApi, function(err){ |
|
// if any of the saves produced an error, err would equal that error |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="map" /> |
|
### map(arr, iterator, callback) |
|
|
|
Produces a new array of values by mapping each value in `arr` through |
|
the `iterator` function. The `iterator` is called with an item from `arr` and a |
|
callback for when it has finished processing. Each of these callback takes 2 arguments: |
|
an `error`, and the transformed item from `arr`. If `iterator` passes an error to his |
|
callback, the main `callback` (for the `map` function) is immediately called with the error. |
|
|
|
Note, that since this function applies the `iterator` to each item in parallel, |
|
there is no guarantee that the `iterator` functions will complete in order. |
|
However, the results array will be in the same order as the original `arr`. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A function to apply to each item in `arr`. |
|
The iterator is passed a `callback(err, transformed)` which must be called once |
|
it has completed with an error (which can be `null`) and a transformed item. |
|
* `callback(err, results)` - A callback which is called when all `iterator` |
|
functions have finished, or an error occurs. Results is an array of the |
|
transformed items from the `arr`. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.map(['file1','file2','file3'], fs.stat, function(err, results){ |
|
// results is now an array of stats for each file |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="mapSeries" /> |
|
### mapSeries(arr, iterator, callback) |
|
|
|
The same as [`map`](#map), only the `iterator` is applied to each item in `arr` in |
|
series. The next `iterator` is only called once the current one has completed. |
|
The results array will be in the same order as the original. |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="mapLimit" /> |
|
### mapLimit(arr, limit, iterator, callback) |
|
|
|
The same as [`map`](#map), only no more than `limit` `iterator`s will be simultaneously |
|
running at any time. |
|
|
|
Note that the items are not processed in batches, so there is no guarantee that |
|
the first `limit` `iterator` functions will complete before any others are started. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `limit` - The maximum number of `iterator`s to run at any time. |
|
* `iterator(item, callback)` - A function to apply to each item in `arr`. |
|
The iterator is passed a `callback(err, transformed)` which must be called once |
|
it has completed with an error (which can be `null`) and a transformed item. |
|
* `callback(err, results)` - A callback which is called when all `iterator` |
|
calls have finished, or an error occurs. The result is an array of the |
|
transformed items from the original `arr`. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){ |
|
// results is now an array of stats for each file |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="select" /> |
|
<a name="filter" /> |
|
### filter(arr, iterator, callback) |
|
|
|
__Alias:__ `select` |
|
|
|
Returns a new array of all the values in `arr` which pass an async truth test. |
|
_The callback for each `iterator` call only accepts a single argument of `true` or |
|
`false`; it does not accept an error argument first!_ This is in-line with the |
|
way node libraries work with truth tests like `fs.exists`. This operation is |
|
performed in parallel, but the results array will be in the same order as the |
|
original. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A truth test to apply to each item in `arr`. |
|
The `iterator` is passed a `callback(truthValue)`, which must be called with a |
|
boolean argument once it has completed. |
|
* `callback(results)` - A callback which is called after all the `iterator` |
|
functions have finished. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.filter(['file1','file2','file3'], fs.exists, function(results){ |
|
// results now equals an array of the existing files |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="selectSeries" /> |
|
<a name="filterSeries" /> |
|
### filterSeries(arr, iterator, callback) |
|
|
|
__Alias:__ `selectSeries` |
|
|
|
The same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in |
|
series. The next `iterator` is only called once the current one has completed. |
|
The results array will be in the same order as the original. |
|
|
|
--------------------------------------- |
|
|
|
<a name="reject" /> |
|
### reject(arr, iterator, callback) |
|
|
|
The opposite of [`filter`](#filter). Removes values that pass an `async` truth test. |
|
|
|
--------------------------------------- |
|
|
|
<a name="rejectSeries" /> |
|
### rejectSeries(arr, iterator, callback) |
|
|
|
The same as [`reject`](#reject), only the `iterator` is applied to each item in `arr` |
|
in series. |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="reduce" /> |
|
### reduce(arr, memo, iterator, callback) |
|
|
|
__Aliases:__ `inject`, `foldl` |
|
|
|
Reduces `arr` into a single value using an async `iterator` to return |
|
each successive step. `memo` is the initial state of the reduction. |
|
This function only operates in series. |
|
|
|
For performance reasons, it may make sense to split a call to this function into |
|
a parallel map, and then use the normal `Array.prototype.reduce` on the results. |
|
This function is for situations where each step in the reduction needs to be async; |
|
if you can get the data before reducing it, then it's probably a good idea to do so. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `memo` - The initial state of the reduction. |
|
* `iterator(memo, item, callback)` - A function applied to each item in the |
|
array to produce the next step in the reduction. The `iterator` is passed a |
|
`callback(err, reduction)` which accepts an optional error as its first |
|
argument, and the state of the reduction as the second. If an error is |
|
passed to the callback, the reduction is stopped and the main `callback` is |
|
immediately called with the error. |
|
* `callback(err, result)` - A callback which is called after all the `iterator` |
|
functions have finished. Result is the reduced value. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.reduce([1,2,3], 0, function(memo, item, callback){ |
|
// pointless async: |
|
process.nextTick(function(){ |
|
callback(null, memo + item) |
|
}); |
|
}, function(err, result){ |
|
// result is now equal to the last value of memo, which is 6 |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="reduceRight" /> |
|
### reduceRight(arr, memo, iterator, callback) |
|
|
|
__Alias:__ `foldr` |
|
|
|
Same as [`reduce`](#reduce), only operates on `arr` in reverse order. |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="detect" /> |
|
### detect(arr, iterator, callback) |
|
|
|
Returns the first value in `arr` that passes an async truth test. The |
|
`iterator` is applied in parallel, meaning the first iterator to return `true` will |
|
fire the detect `callback` with that result. That means the result might not be |
|
the first item in the original `arr` (in terms of order) that passes the test. |
|
|
|
If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries). |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A truth test to apply to each item in `arr`. |
|
The iterator is passed a `callback(truthValue)` which must be called with a |
|
boolean argument once it has completed. |
|
* `callback(result)` - A callback which is called as soon as any iterator returns |
|
`true`, or after all the `iterator` functions have finished. Result will be |
|
the first item in the array that passes the truth test (iterator) or the |
|
value `undefined` if none passed. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.detect(['file1','file2','file3'], fs.exists, function(result){ |
|
// result now equals the first file in the list that exists |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="detectSeries" /> |
|
### detectSeries(arr, iterator, callback) |
|
|
|
The same as [`detect`](#detect), only the `iterator` is applied to each item in `arr` |
|
in series. This means the result is always the first in the original `arr` (in |
|
terms of array order) that passes the truth test. |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="sortBy" /> |
|
### sortBy(arr, iterator, callback) |
|
|
|
Sorts a list by the results of running each `arr` value through an async `iterator`. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A function to apply to each item in `arr`. |
|
The iterator is passed a `callback(err, sortValue)` which must be called once it |
|
has completed with an error (which can be `null`) and a value to use as the sort |
|
criteria. |
|
* `callback(err, results)` - A callback which is called after all the `iterator` |
|
functions have finished, or an error occurs. Results is the items from |
|
the original `arr` sorted by the values returned by the `iterator` calls. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.sortBy(['file1','file2','file3'], function(file, callback){ |
|
fs.stat(file, function(err, stats){ |
|
callback(err, stats.mtime); |
|
}); |
|
}, function(err, results){ |
|
// results is now the original array of files sorted by |
|
// modified date |
|
}); |
|
``` |
|
|
|
__Sort Order__ |
|
|
|
By modifying the callback parameter the sorting order can be influenced: |
|
|
|
```js |
|
//ascending order |
|
async.sortBy([1,9,3,5], function(x, callback){ |
|
callback(null, x); |
|
}, function(err,result){ |
|
//result callback |
|
} ); |
|
|
|
//descending order |
|
async.sortBy([1,9,3,5], function(x, callback){ |
|
callback(null, x*-1); //<- x*-1 instead of x, turns the order around |
|
}, function(err,result){ |
|
//result callback |
|
} ); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="some" /> |
|
### some(arr, iterator, callback) |
|
|
|
__Alias:__ `any` |
|
|
|
Returns `true` if at least one element in the `arr` satisfies an async test. |
|
_The callback for each iterator call only accepts a single argument of `true` or |
|
`false`; it does not accept an error argument first!_ This is in-line with the |
|
way node libraries work with truth tests like `fs.exists`. Once any iterator |
|
call returns `true`, the main `callback` is immediately called. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A truth test to apply to each item in the array |
|
in parallel. The iterator is passed a callback(truthValue) which must be |
|
called with a boolean argument once it has completed. |
|
* `callback(result)` - A callback which is called as soon as any iterator returns |
|
`true`, or after all the iterator functions have finished. Result will be |
|
either `true` or `false` depending on the values of the async tests. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.some(['file1','file2','file3'], fs.exists, function(result){ |
|
// if result is true then at least one of the files exists |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="every" /> |
|
### every(arr, iterator, callback) |
|
|
|
__Alias:__ `all` |
|
|
|
Returns `true` if every element in `arr` satisfies an async test. |
|
_The callback for each `iterator` call only accepts a single argument of `true` or |
|
`false`; it does not accept an error argument first!_ This is in-line with the |
|
way node libraries work with truth tests like `fs.exists`. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A truth test to apply to each item in the array |
|
in parallel. The iterator is passed a callback(truthValue) which must be |
|
called with a boolean argument once it has completed. |
|
* `callback(result)` - A callback which is called after all the `iterator` |
|
functions have finished. Result will be either `true` or `false` depending on |
|
the values of the async tests. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.every(['file1','file2','file3'], fs.exists, function(result){ |
|
// if result is true then every file exists |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="concat" /> |
|
### concat(arr, iterator, callback) |
|
|
|
Applies `iterator` to each item in `arr`, concatenating the results. Returns the |
|
concatenated list. The `iterator`s are called in parallel, and the results are |
|
concatenated as they return. There is no guarantee that the results array will |
|
be returned in the original order of `arr` passed to the `iterator` function. |
|
|
|
__Arguments__ |
|
|
|
* `arr` - An array to iterate over. |
|
* `iterator(item, callback)` - A function to apply to each item in `arr`. |
|
The iterator is passed a `callback(err, results)` which must be called once it |
|
has completed with an error (which can be `null`) and an array of results. |
|
* `callback(err, results)` - A callback which is called after all the `iterator` |
|
functions have finished, or an error occurs. Results is an array containing |
|
the concatenated results of the `iterator` function. |
|
|
|
__Example__ |
|
|
|
```js |
|
async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ |
|
// files is now a list of filenames that exist in the 3 directories |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="concatSeries" /> |
|
### concatSeries(arr, iterator, callback) |
|
|
|
Same as [`concat`](#concat), but executes in series instead of parallel. |
|
|
|
|
|
## Control Flow |
|
|
|
<a name="series" /> |
|
### series(tasks, [callback]) |
|
|
|
Run the functions in the `tasks` array 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 Specifcation](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. |
|
|
|
__Arguments__ |
|
|
|
* `tasks` - An array or object 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. |
|
* `callback(err, results)` - 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. |
|
|
|
__Example__ |
|
|
|
```js |
|
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'] |
|
}); |
|
|
|
|
|
// an example using an object instead of an array |
|
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} |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="parallel" /> |
|
### parallel(tasks, [callback]) |
|
|
|
Run the `tasks` array 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. |
|
|
|
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). |
|
|
|
|
|
__Arguments__ |
|
|
|
* `tasks` - An array or object 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. |
|
* `callback(err, results)` - 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. |
|
|
|
__Example__ |
|
|
|
```js |
|
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} |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="parallelLimit" /> |
|
### parallelLimit(tasks, limit, [callback]) |
|
|
|
The same as [`parallel`](#parallel), only `tasks` are executed in parallel |
|
with a maximum of `limit` tasks executing at any time. |
|
|
|
Note that the `tasks` are not executed in batches, so there is no guarantee that |
|
the first `limit` tasks will complete before any others are started. |
|
|
|
__Arguments__ |
|
|
|
* `tasks` - An array or object 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. |
|
* `limit` - The maximum number of `tasks` to run at any time. |
|
* `callback(err, results)` - 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. |
|
|
|
--------------------------------------- |
|
|
|
<a name="whilst" /> |
|
### whilst(test, fn, callback) |
|
|
|
Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped, |
|
or an error occurs. |
|
|
|
__Arguments__ |
|
|
|
* `test()` - synchronous truth test to perform before each execution of `fn`. |
|
* `fn(callback)` - 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. |
|
* `callback(err)` - A callback which is called after the test fails and repeated |
|
execution of `fn` has stopped. |
|
|
|
__Example__ |
|
|
|
```js |
|
var count = 0; |
|
|
|
async.whilst( |
|
function () { return count < 5; }, |
|
function (callback) { |
|
count++; |
|
setTimeout(callback, 1000); |
|
}, |
|
function (err) { |
|
// 5 seconds have passed |
|
} |
|
); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="doWhilst" /> |
|
### doWhilst(fn, test, callback) |
|
|
|
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. |
|
|
|
--------------------------------------- |
|
|
|
<a name="until" /> |
|
### until(test, fn, callback) |
|
|
|
Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped, |
|
or an error occurs. |
|
|
|
The inverse of [`whilst`](#whilst). |
|
|
|
--------------------------------------- |
|
|
|
<a name="doUntil" /> |
|
### doUntil(fn, test, callback) |
|
|
|
Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`. |
|
|
|
--------------------------------------- |
|
|
|
<a name="forever" /> |
|
### forever(fn, errback) |
|
|
|
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. |
|
|
|
```js |
|
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. |
|
} |
|
); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="waterfall" /> |
|
### waterfall(tasks, [callback]) |
|
|
|
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. |
|
|
|
__Arguments__ |
|
|
|
* `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. |
|
* `callback(err, [results])` - An optional callback to run once all the functions |
|
have completed. This will be passed the results of the last task's callback. |
|
|
|
|
|
|
|
__Example__ |
|
|
|
```js |
|
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' |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
<a name="compose" /> |
|
### compose(fn1, fn2...) |
|
|
|
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. |
|
|
|
__Arguments__ |
|
|
|
* `functions...` - the asynchronous functions to compose |
|
|
|
|
|
__Example__ |
|
|
|
```js |
|
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 |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
<a name="seq" /> |
|
### seq(fn1, fn2...) |
|
|
|
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. |
|
|
|
__Arguments__ |
|
|
|
* functions... - the asynchronous functions to compose |
|
|
|
|
|
__Example__ |
|
|
|
```js |
|
// 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 }); |
|
} |
|
}); |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
<a name="applyEach" /> |
|
### applyEach(fns, args..., callback) |
|
|
|
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. |
|
|
|
__Arguments__ |
|
|
|
* `fns` - the asynchronous functions to all call with the same arguments |
|
* `args...` - any number of separate arguments to pass to the function |
|
* `callback` - the final argument should be the callback, called when all |
|
functions have completed processing |
|
|
|
|
|
__Example__ |
|
|
|
```js |
|
async.applyEach([enableSearch, updateSchema], 'bucket', callback); |
|
|
|
// partial application example: |
|
async.each( |
|
buckets, |
|
async.applyEach([enableSearch, updateSchema]), |
|
callback |
|
); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="applyEachSeries" /> |
|
### applyEachSeries(arr, iterator, callback) |
|
|
|
The same as [`applyEach`](#applyEach) only the functions are applied in series. |
|
|
|
--------------------------------------- |
|
|
|
<a name="queue" /> |
|
### queue(worker, concurrency) |
|
|
|
Creates a `queue` object with the specified `concurrency`. Tasks added to the |
|
`queue` are processed in parallel (up to the `concurrency` limit). If all |
|
`worker`s are in progress, the task is queued until one becomes available. |
|
Once a `worker` completes a `task`, that `task`'s callback is called. |
|
|
|
__Arguments__ |
|
|
|
* `worker(task, callback)` - An asynchronous function for processing a queued |
|
task, which must call its `callback(err)` argument when finished, with an |
|
optional `error` as an argument. |
|
* `concurrency` - An `integer` for determining how many `worker` functions should be |
|
run in parallel. |
|
|
|
__Queue objects__ |
|
|
|
The `queue` object returned by this function has the following properties and |
|
methods: |
|
|
|
* `length()` - a function returning the number of items waiting to be processed. |
|
* `started` - a function returning whether or not any items have been pushed and processed by the queue |
|
* `running()` - a function returning the number of items currently being processed. |
|
* `idle()` - a function returning false if there are items waiting or being processed, or true if not. |
|
* `concurrency` - an integer for determining how many `worker` functions should be |
|
run in parallel. This property can be changed after a `queue` is created to |
|
alter the concurrency on-the-fly. |
|
* `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once |
|
the `worker` has finished processing the task. Instead of a single task, a `tasks` array |
|
can be submitted. The respective callback is used for every task in the list. |
|
* `unshift(task, [callback])` - add a new task to the front of the `queue`. |
|
* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit, |
|
and further tasks will be queued. |
|
* `empty` - a callback that is called when the last item from the `queue` is given to a `worker`. |
|
* `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`. |
|
* `paused` - a boolean for determining whether the queue is in a paused state |
|
* `pause()` - a function that pauses the processing of tasks until `resume()` is called. |
|
* `resume()` - a function that resumes the processing of queued tasks when the queue is paused. |
|
* `kill()` - a function that removes the `drain` callback and empties remaining tasks from the queue forcing it to go idle. |
|
|
|
__Example__ |
|
|
|
```js |
|
// create a queue object with concurrency 2 |
|
|
|
var q = async.queue(function (task, callback) { |
|
console.log('hello ' + task.name); |
|
callback(); |
|
}, 2); |
|
|
|
|
|
// assign a callback |
|
q.drain = function() { |
|
console.log('all items have been processed'); |
|
} |
|
|
|
// add some items to the queue |
|
|
|
q.push({name: 'foo'}, function (err) { |
|
console.log('finished processing foo'); |
|
}); |
|
q.push({name: 'bar'}, function (err) { |
|
console.log('finished processing bar'); |
|
}); |
|
|
|
// add some items to the queue (batch-wise) |
|
|
|
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { |
|
console.log('finished processing item'); |
|
}); |
|
|
|
// add some items to the front of the queue |
|
|
|
q.unshift({name: 'bar'}, function (err) { |
|
console.log('finished processing bar'); |
|
}); |
|
``` |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="priorityQueue" /> |
|
### priorityQueue(worker, concurrency) |
|
|
|
The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects: |
|
|
|
* `push(task, priority, [callback])` - `priority` should be a number. If an array of |
|
`tasks` is given, all tasks will be assigned the same priority. |
|
* The `unshift` method was removed. |
|
|
|
--------------------------------------- |
|
|
|
<a name="cargo" /> |
|
### cargo(worker, [payload]) |
|
|
|
Creates a `cargo` object with the specified payload. Tasks added to the |
|
cargo will be processed altogether (up to the `payload` limit). If the |
|
`worker` is in progress, the task is queued until it becomes available. Once |
|
the `worker` has completed some tasks, each callback of those tasks is called. |
|
Check out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work. |
|
|
|
While [queue](#queue) passes only one task to one of a group of workers |
|
at a time, cargo passes an array of tasks to a single worker, repeating |
|
when the worker is finished. |
|
|
|
__Arguments__ |
|
|
|
* `worker(tasks, callback)` - An asynchronous function for processing an array of |
|
queued tasks, which must call its `callback(err)` argument when finished, with |
|
an optional `err` argument. |
|
* `payload` - An optional `integer` for determining how many tasks should be |
|
processed per round; if omitted, the default is unlimited. |
|
|
|
__Cargo objects__ |
|
|
|
The `cargo` object returned by this function has the following properties and |
|
methods: |
|
|
|
* `length()` - A function returning the number of items waiting to be processed. |
|
* `payload` - An `integer` for determining how many tasks should be |
|
process per round. This property can be changed after a `cargo` is created to |
|
alter the payload on-the-fly. |
|
* `push(task, [callback])` - Adds `task` to the `queue`. The callback is called |
|
once the `worker` has finished processing the task. Instead of a single task, an array of `tasks` |
|
can be submitted. The respective callback is used for every task in the list. |
|
* `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued. |
|
* `empty` - A callback that is called when the last item from the `queue` is given to a `worker`. |
|
* `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`. |
|
|
|
__Example__ |
|
|
|
```js |
|
// create a cargo object with payload 2 |
|
|
|
var cargo = async.cargo(function (tasks, callback) { |
|
for(var i=0; i<tasks.length; i++){ |
|
console.log('hello ' + tasks[i].name); |
|
} |
|
callback(); |
|
}, 2); |
|
|
|
|
|
// add some items |
|
|
|
cargo.push({name: 'foo'}, function (err) { |
|
console.log('finished processing foo'); |
|
}); |
|
cargo.push({name: 'bar'}, function (err) { |
|
console.log('finished processing bar'); |
|
}); |
|
cargo.push({name: 'baz'}, function (err) { |
|
console.log('finished processing baz'); |
|
}); |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="auto" /> |
|
### auto(tasks, [callback]) |
|
|
|
Determines the best order for running the functions in `tasks`, based on their |
|
requirements. Each function can optionally depend on other functions being completed |
|
first, and each function is run as soon as its requirements are satisfied. |
|
|
|
If any of the functions pass an error to their callback, it will not |
|
complete (so any other functions depending on it will not run), and the main |
|
`callback` is immediately called with the error. Functions also receive an |
|
object containing the results of functions which have completed so far. |
|
|
|
Note, all functions are called with a `results` object as a second argument, |
|
so it is unsafe to pass functions in the `tasks` object which cannot handle the |
|
extra argument. |
|
|
|
For example, this snippet of code: |
|
|
|
```js |
|
async.auto({ |
|
readData: async.apply(fs.readFile, 'data.txt', 'utf-8') |
|
}, callback); |
|
``` |
|
|
|
will have the effect of calling `readFile` with the results object as the last |
|
argument, which will fail: |
|
|
|
```js |
|
fs.readFile('data.txt', 'utf-8', cb, {}); |
|
``` |
|
|
|
Instead, wrap the call to `readFile` in a function which does not forward the |
|
`results` object: |
|
|
|
```js |
|
async.auto({ |
|
readData: function(cb, results){ |
|
fs.readFile('data.txt', 'utf-8', cb); |
|
} |
|
}, callback); |
|
``` |
|
|
|
__Arguments__ |
|
|
|
* `tasks` - An object. Each of its properties is either a function or an array of |
|
requirements, with the function itself the last item in the array. The object's key |
|
of a property serves as the name of the task defined by that property, |
|
i.e. can be used when specifying requirements for other tasks. |
|
The function receives two arguments: (1) a `callback(err, result)` which must be |
|
called when finished, passing an `error` (which can be `null`) and the result of |
|
the function's execution, and (2) a `results` object, containing the results of |
|
the previously executed functions. |
|
* `callback(err, results)` - An optional callback which is called when all the |
|
tasks have been completed. It receives the `err` argument if any `tasks` |
|
pass an error to their callback. Results are always returned; however, if |
|
an error occurs, no further `tasks` will be performed, and the results |
|
object will only contain partial results. |
|
|
|
|
|
__Example__ |
|
|
|
```js |
|
async.auto({ |
|
get_data: function(callback){ |
|
console.log('in get_data'); |
|
// async code to get some data |
|
callback(null, 'data', 'converted to array'); |
|
}, |
|
make_folder: function(callback){ |
|
console.log('in make_folder'); |
|
// async code to create a directory to store a file in |
|
// this is run at the same time as getting the data |
|
callback(null, 'folder'); |
|
}, |
|
write_file: ['get_data', 'make_folder', function(callback, results){ |
|
console.log('in write_file', JSON.stringify(results)); |
|
// once there is some data and the directory exists, |
|
// write the data to a file in the directory |
|
callback(null, 'filename'); |
|
}], |
|
email_link: ['write_file', function(callback, results){ |
|
console.log('in email_link', JSON.stringify(results)); |
|
// once the file is written let's email a link to it... |
|
// results.write_file contains the filename returned by write_file. |
|
callback(null, {'file':results.write_file, 'email':'[email protected]'}); |
|
}] |
|
}, function(err, results) { |
|
console.log('err = ', err); |
|
console.log('results = ', results); |
|
}); |
|
``` |
|
|
|
This is a fairly trivial example, but to do this using the basic parallel and |
|
series functions would look like this: |
|
|
|
```js |
|
async.parallel([ |
|
function(callback){ |
|
console.log('in get_data'); |
|
// async code to get some data |
|
callback(null, 'data', 'converted to array'); |
|
}, |
|
function(callback){ |
|
console.log('in make_folder'); |
|
// async code to create a directory to store a file in |
|
// this is run at the same time as getting the data |
|
callback(null, 'folder'); |
|
} |
|
], |
|
function(err, results){ |
|
async.series([ |
|
function(callback){ |
|
console.log('in write_file', JSON.stringify(results)); |
|
// once there is some data and the directory exists, |
|
// write the data to a file in the directory |
|
results.push('filename'); |
|
callback(null); |
|
}, |
|
function(callback){ |
|
console.log('in email_link', JSON.stringify(results)); |
|
// once the file is written let's email a link to it... |
|
callback(null, {'file':results.pop(), 'email':'[email protected]'}); |
|
} |
|
]); |
|
}); |
|
``` |
|
|
|
For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding |
|
new tasks much easier (and the code more readable). |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="retry" /> |
|
### retry([times = 5], task, [callback]) |
|
|
|
Attempts to get a successful response from `task` no more than `times` times before |
|
returning an error. If the task is successful, the `callback` will be passed the result |
|
of the successful task. If all attempts fail, the callback will be passed the error and |
|
result (if any) of the final attempt. |
|
|
|
__Arguments__ |
|
|
|
* `times` - An integer indicating how many times to attempt the `task` before giving up. Defaults to 5. |
|
* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)` |
|
which must be called when finished, passing `err` (which can be `null`) and the `result` of |
|
the function's execution, and (2) a `results` object, containing the results of |
|
the previously executed functions (if nested inside another control flow). |
|
* `callback(err, results)` - An optional callback which is called when the |
|
task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`. |
|
|
|
The [`retry`](#retry) function can be used as a stand-alone control flow by passing a |
|
callback, as shown below: |
|
|
|
```js |
|
async.retry(3, apiMethod, function(err, result) { |
|
// do something with the result |
|
}); |
|
``` |
|
|
|
It can also be embeded within other control flow functions to retry individual methods |
|
that are not as reliable, like this: |
|
|
|
```js |
|
async.auto({ |
|
users: api.getUsers.bind(api), |
|
payments: async.retry(3, api.getPayments.bind(api)) |
|
}, function(err, results) { |
|
// do something with the results |
|
}); |
|
``` |
|
|
|
|
|
--------------------------------------- |
|
|
|
<a name="iterator" /> |
|
### iterator(tasks) |
|
|
|
Creates an iterator function which calls the next function in the `tasks` array, |
|
returning a continuation to call the next one after that. It's also possible to |
|
“peek” at the next iterator with `iterator.next()`. |
|
|
|
This function is used internally by the `async` module, but can be useful when |
|
you want to manually control the flow of functions in series. |
|
|
|
__Arguments__ |
|
|
|
* `tasks` - An array of functions to run. |
|
|
|
__Example__ |
|
|
|
```js |
|
var iterator = async.iterator([ |
|
function(){ sys.p('one'); }, |
|
function(){ sys.p('two'); }, |
|
function(){ sys.p('three'); } |
|
]); |
|
|
|
node> var iterator2 = iterator(); |
|
'one' |
|
node> var iterator3 = iterator2(); |
|
'two' |
|
node> iterator3(); |
|
'three' |
|
node> var nextfn = iterator2.next(); |
|
node> nextfn(); |
|
'three' |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="apply" /> |
|
### apply(function, arguments..) |
|
|
|
Creates a continuation function with some arguments already applied. |
|
|
|
Useful as a shorthand when combined with other control flow functions. Any arguments |
|
passed to the returned function are added to the arguments originally passed |
|
to apply. |
|
|
|
__Arguments__ |
|
|
|
* `function` - The function you want to eventually apply all arguments to. |
|
* `arguments...` - Any number of arguments to automatically apply when the |
|
continuation is called. |
|
|
|
__Example__ |
|
|
|
```js |
|
// using apply |
|
|
|
async.parallel([ |
|
async.apply(fs.writeFile, 'testfile1', 'test1'), |
|
async.apply(fs.writeFile, 'testfile2', 'test2'), |
|
]); |
|
|
|
|
|
// the same process without using apply |
|
|
|
async.parallel([ |
|
function(callback){ |
|
fs.writeFile('testfile1', 'test1', callback); |
|
}, |
|
function(callback){ |
|
fs.writeFile('testfile2', 'test2', callback); |
|
} |
|
]); |
|
``` |
|
|
|
It's possible to pass any number of additional arguments when calling the |
|
continuation: |
|
|
|
```js |
|
node> var fn = async.apply(sys.puts, 'one'); |
|
node> fn('two', 'three'); |
|
one |
|
two |
|
three |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="nextTick" /> |
|
### nextTick(callback), setImmediate(callback) |
|
|
|
Calls `callback` on a later loop around the event loop. In Node.js this just |
|
calls `process.nextTick`; in the browser it falls back to `setImmediate(callback)` |
|
if available, otherwise `setTimeout(callback, 0)`, which means other higher priority |
|
events may precede the execution of `callback`. |
|
|
|
This is used internally for browser-compatibility purposes. |
|
|
|
__Arguments__ |
|
|
|
* `callback` - The function to call on a later loop around the event loop. |
|
|
|
__Example__ |
|
|
|
```js |
|
var call_order = []; |
|
async.nextTick(function(){ |
|
call_order.push('two'); |
|
// call_order now equals ['one','two'] |
|
}); |
|
call_order.push('one') |
|
``` |
|
|
|
<a name="times" /> |
|
### times(n, callback) |
|
|
|
Calls the `callback` function `n` times, and accumulates results in the same manner |
|
you would use with [`map`](#map). |
|
|
|
__Arguments__ |
|
|
|
* `n` - The number of times to run the function. |
|
* `callback` - The function to call `n` times. |
|
|
|
__Example__ |
|
|
|
```js |
|
// Pretend this is some complicated async factory |
|
var createUser = function(id, callback) { |
|
callback(null, { |
|
id: 'user' + id |
|
}) |
|
} |
|
// generate 5 users |
|
async.times(5, function(n, next){ |
|
createUser(n, function(err, user) { |
|
next(err, user) |
|
}) |
|
}, function(err, users) { |
|
// we should now have 5 users |
|
}); |
|
``` |
|
|
|
<a name="timesSeries" /> |
|
### timesSeries(n, callback) |
|
|
|
The same as [`times`](#times), only the iterator is applied to each item in `arr` in |
|
series. The next `iterator` is only called once the current one has completed. |
|
The results array will be in the same order as the original. |
|
|
|
|
|
## Utils |
|
|
|
<a name="memoize" /> |
|
### memoize(fn, [hasher]) |
|
|
|
Caches the results of an `async` function. When creating a hash to store function |
|
results against, the callback is omitted from the hash and an optional hash |
|
function can be used. |
|
|
|
The cache of results is exposed as the `memo` property of the function returned |
|
by `memoize`. |
|
|
|
__Arguments__ |
|
|
|
* `fn` - The function to proxy and cache results from. |
|
* `hasher` - Tn optional function for generating a custom hash for storing |
|
results. It has all the arguments applied to it apart from the callback, and |
|
must be synchronous. |
|
|
|
__Example__ |
|
|
|
```js |
|
var slow_fn = function (name, callback) { |
|
// do something |
|
callback(null, result); |
|
}; |
|
var fn = async.memoize(slow_fn); |
|
|
|
// fn can now be used as if it were slow_fn |
|
fn('some name', function () { |
|
// callback |
|
}); |
|
``` |
|
|
|
<a name="unmemoize" /> |
|
### unmemoize(fn) |
|
|
|
Undoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized |
|
form. Handy for testing. |
|
|
|
__Arguments__ |
|
|
|
* `fn` - the memoized function |
|
|
|
<a name="log" /> |
|
### log(function, arguments) |
|
|
|
Logs the result of an `async` function to the `console`. Only works in Node.js or |
|
in browsers that support `console.log` and `console.error` (such as FF and Chrome). |
|
If multiple arguments are returned from the async function, `console.log` is |
|
called on each argument in order. |
|
|
|
__Arguments__ |
|
|
|
* `function` - The function you want to eventually apply all arguments to. |
|
* `arguments...` - Any number of arguments to apply to the function. |
|
|
|
__Example__ |
|
|
|
```js |
|
var hello = function(name, callback){ |
|
setTimeout(function(){ |
|
callback(null, 'hello ' + name); |
|
}, 1000); |
|
}; |
|
``` |
|
```js |
|
node> async.log(hello, 'world'); |
|
'hello world' |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="dir" /> |
|
### dir(function, arguments) |
|
|
|
Logs the result of an `async` function to the `console` using `console.dir` to |
|
display the properties of the resulting object. Only works in Node.js or |
|
in browsers that support `console.dir` and `console.error` (such as FF and Chrome). |
|
If multiple arguments are returned from the async function, `console.dir` is |
|
called on each argument in order. |
|
|
|
__Arguments__ |
|
|
|
* `function` - The function you want to eventually apply all arguments to. |
|
* `arguments...` - Any number of arguments to apply to the function. |
|
|
|
__Example__ |
|
|
|
```js |
|
var hello = function(name, callback){ |
|
setTimeout(function(){ |
|
callback(null, {hello: name}); |
|
}, 1000); |
|
}; |
|
``` |
|
```js |
|
node> async.dir(hello, 'world'); |
|
{hello: 'world'} |
|
``` |
|
|
|
--------------------------------------- |
|
|
|
<a name="noConflict" /> |
|
### noConflict() |
|
|
|
Changes the value of `async` back to its original value, returning a reference to the |
|
`async` object. |
|
|