Provides a single callback for multiple asynchronous calls
Finish is a high performance nodejs flow control utility that captures completion of multiple asynchronous calls with a single callback.
You can install using Node Package Manager (npm):
npm install finish
var finish = require"finish";finish// Any asynchronous calls within this function will be captured// Just wrap each asynchronous call with function 'async'.// Each asynchronous call should invoke 'done' as its callback.// 'done' tasks two arguments: error and result.async fsreadFile'hello.txt' done;async fsreadFile'world.txt' done;// This callback is invoked after all asynchronous calls finish// or as soon as an error occurs// results is an array that contains result of each asynchronous callconsole.logresults0 results1;;
Finish provides four APIs:
finishfunc reducer initialValue callback;finishmaparray async reducer initialValue callback;finishorderedfunc reducer initialValue callback;finishorderedmaparray async reducer initialValue callback;
finishfunc reducer initialValue callback
func: function that makes asynchronous calls, taking one argument:
async([key, ]done): wrapper function that wraps an asynchronous call.
key(optional): If provided, result of this call will be added as a property
keyof the final
resultsobject. (See below.)
done: callback function for individual asynchronous calls, taking two arguments:
err: any truthy value of err will cause the final
callbackto be invoked immediately.
result: return value of the asynchronous call; it is captured by the final
reducer(optional): reduction function to execute on each result, taking two arguments:
previousValue: The value previously returned in the last invocation of the
initialValue, if supplied.
currentValue: The current
resultreturned by an asynchronous call.
keyassociated with the
asynccall if provided.
initialValue(optional): Object to use as the first argument to the first call of the
reducer. It omitted, the first
resultreturned by any asynchronous call will be used as
initialValue. This argument should only be used when an
callback: The final callback that will be invoked when all asynchronous calls complete or an error occured, taking two arguments:
err: If an error occured,
erris the error. Otherwise, null.
results: An array of
resultobjects returned by all asynchronous calls. The order of elements of
resultsare not guaranteed (See
finish.orderedif order guarantee is needed). If the optional
keyargument is used in the first
resultswill be an object with null as prototype;
resultwill be properties of
finish is the free form of finish utility. One should wrap each asynchronous
async and the asynchronous call should invoke
done as callback.
Note that it is safe to pass an function to
async that executes
result objects passed to
done is collected into an array if
key parameter of
async is not used. The order of
results are not guaranteed. When
key parameter is used in
results will be an object that has null as prototype; each
result will be an property in
results at the associated
When using an reducer, the reducer is invoked at every
done callback with
result) as arguments. The final
results is the return value of
the last invocation of reducer. The order of reducer invocation is not
guaranteed. One should not use a reducer if
key argument of
async is used.
finishasyncsetTimeout donenull 1; 100;;asyncsetTimeout donenull 2; 100;;assertequalresults 1 2 ;;// "keyed" finishfinishasync"one"setTimeout donenull 1; 100;;async"two"setTimeout donenull 2; 200;;assertequalresults one: 1 two: 2 ;;// with a reducerfinishasyncsetTimeout donenull 1; 100;;asyncsetTimeout donenull 2; 200;;return prev + curr; // reduction operator0 // initial value (can be omitted in this case)assertequalresults 3;;
finishmaparray async reducer initialValue callback
array: An array of elements or an object.
arrayis an instance of Array,
asyncwill be invoked on every element of
asyncwill be invoked on
array's own enumerable properties. Depends on how many arguments
asyncis invoked with:
(value, index, done), and
(value, index, array, done).
element: the value of the element or property;
index: the index of the element or the key of the property;
array: the array or object being traversed;
done: the callback function for the asynchronous call (Same as in
reducer(optional): Same reduce function as in
finish. It takes four arguments:
previousValue: Same as in
currentValue: Same as in
index: The index of the corresponding element in
array, or the property name of the corresponding property in
array: The same
initialValue(optional): Same as in
callback: Same as in
This is an syntactic sugar for
finish. It maps the
async function onto each
element (or property, if
array is not an instance of Array) of
finish, the order of execution is not guaranteed either.
// map an arrayfinishmap1 2 3setTimeout donenull value; ;assertequalresults 1 2 3;;// map an objectfinishmap one: 1 two: 2 three: 3setTimeout donenull value; ;assertequalresults one: 1 two: 2 three: 3 ;;
finishorderedfunc reducer initialValue callbackfinishorderedmaparray async reducer initialValue callback
These two functions is the same as
finish.map with the addition
of order guarantee. The order of
result objects in
results are guaranteed to
be the same as the order of invocation of asynchronous calls. If using a
reducer, the reducer is invoked in the same order as the asynchronous calls
Async.parallel accepts an array of continuation functions and runs them in parallel. It also provides a callback function which is fired after all functions finish. Finish differs from async.parallel because it does not require user to pack asynchronous calls into an array to run them in parallel and track their completion. This gives you more flexibility and greatly reduce the lines of plateboiler code you need to write when using Async.parallel. Moreover, it increase parallelism, which gives you better performance.
Examples folder contains an example which calculates a size of a directory, implemented in both finish and async.parallel. Here's how they perform on my macbook:
$ time node size.js $HOME /Users/chaorany: 109295.691 MB real 0m11.690s user 0m11.956s sys 0m20.838s $ time node size-async.js $HOME /Users/chaorany: 109295.691 MB real 0m14.348s user 0m14.679s sys 0m21.068s