I prefer the promise pattern.
var firstMethod = function() {
var promise = new Promise(function(resolve, reject){
setTimeout(function() {
console.log('first method completed');
resolve({data: '123'});
}, 2000);
});
return promise;
};
var secondMethod = function(someStuff) {
var promise = new Promise(function(resolve, reject){
setTimeout(function() {
console.log('second method completed');
resolve({newData: someStuff.data + ' some more data'});
}, 2000);
});
return promise;
};
var thirdMethod = function(someStuff) {
var promise = new Promise(function(resolve, reject){
setTimeout(function() {
console.log('third method completed');
resolve({result: someStuff.newData});
}, 3000);
});
return promise;
};
firstMethod()
.then(secondMethod)
.then(thirdMethod);
(Copied shamelessly from: https://html5hive.org/how-to-chain-javascript-promises/ )
It scales better, and looks way better than nesting, once you hit 5-6 functions.
This assumes that you want to execute one function after the other, in that order. If you don't care about order of execution, but just want to make sure that all asynchronous calls have finished, I would take a look at then $.deferred pattern (jQuery). This makes sure that if you have N asynchronous functions and you want the N+1 function to execute after those have completed, you have a clean way to do it.
Example:
var name = $.post('/echo/json/', {json:JSON.stringify({'name':"Matt Baker"})});
var lastUpdate = $.post('/echo/json/', {json:JSON.stringify({'lastUpdate':"Hello World"})});
$.when(name, lastUpdate)
.done(function (nameResponse, lastUpdateResponse) {
var name = nameResponse[0].name;
var lastUpdate = lastUpdateResponse[0].lastUpdate;
$("#render-me").html(name+"'s last update was: "+lastUpdate);
})
.fail(function () {
$("#error").html("an error occured").show();
Copied shamelessly #2 from: http://eng.wealthfront.com/2012/12/04/jquerydeferred-is-most-important-client/
I use the #2nd way for example in UI initialization, when several listboxes, dropdowns and whatever get initialized asynchronously, and want to make sure that the user interface is enabled after all asyncs have finished. Why not do it synchronously you ask? To better utilize the multiple http requests the browser can use. It's faster.