JavaScript Array 'Monkey-Patch' to Execute Functions Sequentially
Here's a monkey-patch for JavaScript Array objects that allows an array of functions to be executed sequentially; that is, one after another. At the end a callback function is executed with an array of Errors (or null if there were none), and an array of responses, which can contain anything you wish.
Let's take a look:
// Add the sequence function to the Array prototype Array.prototype.sequence = function(cb) { var self = this; var index = 0; var errors = [], responses = []; // Recursively call _next until the index reaches the length of this Array function _next(index) { if (index < self.length) { // There's a function to execute, run it... self[index](function(err, res) { if (err) errors.push(err); if (res) responses.push(res); // Increment the index, and execute the next function index ++; _next(index); }); } else { // Reached the end of the array, execute the final callback cb (errors.length > 0 ? errors : null, responses); } } // Start it off _next(0); };
The sequence function is pretty straightforward. First we call _next with an index of 0, in which we check if we have exceeded the length of the array. If so, we execute the final callback (passed to the sequence function). Otherwise, we execute the function at the current index, increment the index, and continue calling _next until we reach the end of the array.
Now let's see it in action:
[ function(next) { console.log('Function 1'); setTimeout(function() { console.log('... timeout complete.'); next(null, true); }, 1000); }, function(next) { console.log('Function 2'); next(null, true); }, function(next) { console.log('Function 3'); next(new Error('Test Error')); } ].sequence(function(err, res) { console.log("----------------------"); console.log("Done With Results:"); console.log(err); console.log(res); });
First up, define an array of functions that you want to execute. Each function must take a callback (called next in the examples above), and execute it upon completion. The callback takes two arguments, the first being an Error (or null), the second being any response you want to pass to the final callback.
Speaking of the final callback, we now call sequence on the array, and give it a callback to execute when all of the functions in the array have finished executing. The final callback will receive two arguments, which are an array of Errors and an array of arbitrary responses, which is the collective sum of all the callbacks you executed in the array of functions. In the example above, the output would look like so:
Function 1 ... timeout complete. Function 2 Function 3 ---------------------- Done With Results: [ [Error: Test Error] ] [ true, true ]
Disclosure
Monkey-patches are a pretty hot topic: some developers avoid them like the plague, and others are all for them. I'm of the latter group, assuming you understand the implications of using them, and aren't just blindly copy-and-pasting all the patches you come across. They can be dangerous, and it's important to understand what the patch is doing before you add it to your codebase.
In addition, this is a pretty short and to-the-point implementation. It has worked for my needs, but may have pitfalls in certain use-cases. However, it should at the very least act as a good starting point, and can be easily customized to suit your needs.