Use promises. Precisely, Promise.all
was designed for this.
It takes an array (or iterable) of promises, and returns a new promise which is resolved when all the promises of the array have been resolved. Otherwise, it rejects when any promise of the array rejects.
function someAsyncFunction(data, resolve, reject) {
setTimeout(function() {
if(Math.random() < .05) {
// Suppose something failed
reject('Error while processing ' + data.someParam);
} else {
// Suppose the current async work completed succesfully
resolve(data.someParam);
}
}, Math.random() * 1000);
}
function foo() {
// Create an array of promises
var promises = [];
for (var i = 0; i < 10; i++) {
// Fill the array with promises which initiate some async work
promises.push(new Promise(function(resolve, reject) {
someAsyncFunction({someParam:i}, resolve, reject);
}));
}
// Return a Promise.all promise of the array
return Promise.all(promises);
}
var result = foo().then(function(results) {
console.log('All async calls completed successfully:');
console.log(' --> ', JSON.stringify(results));
}, function(reason) {
console.log('Some async call failed:');
console.log(' --> ', reason);
});
Note that the results will be given according to the order of the array of promises, not in the order that the promises were resolved in.