Both patterns more or less assume that you are following the Node.js style for passing errors to callbacks–e.g.
The first pattern carries out a series of operations (usually I/O) in order, which helps organize code and avoid indent hell. It is basically a function that calls itself recursively until all operations are complete. Here is an example:
We set up a function named
load() that takes a
results object and a
callback function as arguments. It contains a series of checks that look for loaded data. If the data is missing we attempt to load it. When the async operation is complete we add the result to the
results object and then call the
load() function again. We repeat this process until all of the data is loaded and then finally call the main callback to do something with the gathered results. In this example, an error in any one of the operations will interrupt the process.
The second pattern is for running an asynchronous task in parallel and collecting errors and results along the way.
This time we set up a function that takes an
items array and a
callback as arguments. The function creates a
loaded array with a length that matches that of the
items array. We start the async operations and populate the
loaded array as they complete. Upon each completion we check to see if all other operations are complete by looking at the number of truthy values in the
loaded array. This technique ensures that the order of the items in the output array corresponds to the order of the
items array regardless of actual completion order. The callback is called with the first error but all valid objects and other errors are also returned in the result array in case you want to do further analysis.
*In the browser you will want to use
filter() or even
compact() from underscore.js for compatibility.
Note that this pattern will start all of the async operations at once. If you are looking to throttle parallel async operations and handle error's take a look at basic-queue.
Credit for the conjuring of these patterns goes to Young Hahn.