A long time ago I've answered a very similar question here: Coordinating parallel execution in node.js.
However, times have moved on. Since then a really good library have appeared and the promise design pattern have been fully explored and even standardized into the langauge. If you want to see how it can be done with raw code click the link above. If you just want to code read on..
async.js
The async.js library have basically implemented the code in the link above. With async the code you'd write would look something like this:
var listOfAsyncFunctions = [];
for (var i = 0; i < 10; i++) {
(function(n){
// Construct an array of async functions with the expected
// function signature (one argument that is the callback).
listOfAsyncFunctions.push(function(callback){
// Note: async expects the first argument to callback to be an error
someAsyncFunction({someParam:n}, function (data) {
callback(null,data);
});
})
})(i); // IIFE to break the closure
}
// Note that at this point you haven't called the async functions.
// Pass the array to async.js and let it call them.
async.parallel(listOfAsyncFunctions,function (err,result) {
console.log(result); // result will be the same order as listOfAsyncFunctions
});
However, the authors of async.js have done more than that. Async also have functional array-like operations: each, map, filter, reduce. It makes asynchronously processing arrays simple and makes the code easier to understand:
var listOfParams = [];
for (var i = 0; i < 10; i++) {
// Construct an array of params:
listOfParams.push({someParam:i});
}
async.map(listOfParams,someAsyncFunction,function (err,result) {
console.log(result);
});
Another thing async gives you is different algorithms for how to process the asynchronous tasks. Say for example you want to scrape a website but don't want them to ban your IP address for spamming their server. You can use async.series()
instead of parallel
to process the tasks one at a time:
// Set-up listOfAsyncFunctions as above
async.series(listOfAsyncFunctions,function (err,result) {
console.log(result); // result will be the same order as listOfAsyncFunctions
});
Or if you want to process 3 tasks at a time:
async. parallelLimit(listOfAsyncFunctions, 3, function (err,result) {
console.log(result); // result will be the same order as listOfAsyncFunctions
});
Promise.all()
The Promise.all()
method works in a similar way to async.parallel()
only it works with promises instead. You construct an array of promises then pass them to Promise.all()
:
var listOfPromises = [];
for (var i = 0; i < 10; i++) {
// Construct an array of promises
listOfPromises.push(somePromiseFunction({someParam:i}));
}
Promise.all(listOfPromises).then(function(result){
console.log(result);
});