Popular Control Flow Libraries
When writing asynchronous code it quickly becomes apparent that certain patterns are more natural than others. These patterns are fairly generic, so many people have started to rely on control flow libraries rather than reimplementing the same patterns.
There are a lot of control flow libraries for Node, and they all solve the same problems in subtly different ways. Some are more accurate than others with regard to established nomenclature, particularly when it comes to design patterns that were already popular in other languages.
People usually discover the need for control flow libraries when running something like this:
files.forEach(function(file) {
fs.readFile(file, function() {
// Callback
});
});
A set of files is going to be read with an asynchronous callback. That’s great, but what happens when we need to determine when every callback has finished?
One solution is to use a counter:
files.forEach(function(file) {
fs.readFile(file, function() {
// Callback
fileCount--;
if (fileCount === 0) {
events.emit('complete');
}
});
});
events.on('complete', function() {
// All files have been processed
});
However, adding a few more levels of asynchronous dependencies will make this hard to manage. This is where libraries step in to provide another layer of abstraction.
One such library is Tim Caswell’s Step, which is probably the first control flow library I saw:
Step(
function readSelf() {
fs.readFile(__filename, this);
},
function capitalize(err, text) {
if (err) throw err;
return text.toUpperCase();
},
function showIt(err, newText) {
if (err) throw err;
console.log(newText);
}
);
There are dozens of other, similar libraries available through npm. Which one should you use? I’ve made a table of the popular ones to try to get a handle on the situation. Post your favourites in the comments and I’ll take a look at them.
| Name | NPM | License | Dependent Packages | GitHub Watchers | Features | Browser Support |
|---|---|---|---|---|---|---|
| Async.js | async | MIT | 129 | 982 | Parallel execution of ‘functional’ methods, generic parallel, serial, and waterfall methods | Yes |
| Step | Step | MIT | 42 | 462 | Parallel and serial execution, error handling, grouping | Yes |
| Futures | futures | MIT | 6 | 190 | Promises, “joins”, events, chained sequences, method queues, sequences | Yes |
| Seq | seq | MIT/X11 | 14 | 124 | Sequential and parallel execution, error handling, chained API | No |
