Avoiding nested asynchronous calls in JS
Rather than having two nested (asynchronous) calls in order make sure the one loads to execute the other, you can use deffereds. Check out jQuery.when( deferreds ). Query the calls with $.when, and use a chained ".then" which happens when this calls get resolved or rejected. Seems a lot human readable to me.
// Nested calls
function doSomething(){
$.getJSON('/api/users', function(data) {
var Users = data.users;
$.getJSON('/api/skills', function(data) {
// doSomethingElse( Users, data.skills ); // do callback
});
});
}
// Cleaner
function doSomething(){
$.when( $.getJSON('/api/users'), $.getJSON('api/skills') ).then(function( users, skills ){
// doSomethingElse( users, skills ); // both resolved here
});
}
Written by Ignacio Chavez
Related protips
7 Responses
When multiple AJAX calls are used with a jQuery deferred, isn't it correct that they will run in parallel? In this case, your example is not only easier to read, but has a performance boost. The only disadvantage that should be noted is that if there is a data dependency for the second request, based on the result of the first request, then they need to be nested so that they execute in sequence rather than in parallel.
@jm9000 Hm, really, I was actually under the impression that this abstraction was a bit slower but prettier.
@jm9000 Holly, 1 sec?, that seems a lot. I'm gonna do a test myself to confirm this.
@nashio Of course it is a lot. The delay is to accentuate the performance difference. I would never have any delay at all in a real application.
This pattern is called deferred and promises.
Not to mention, there is a whole class of different methods to solving the callback hell problem that everyone is talking about.
An alternative library is async.js. However, it doesn't handle asynchronous calls via promises.
Another one is the Q library. This one uses promises just like jQuery. If you mix Q with async, you can get elegant asynchronous calls.
What if the second getJSON call requires the result Users? i.e. how do you sequence two or more promises when each subsequent promise relies on the prior's result (without nesting?)