In my JS, I need to get the contents of 3 files with AJAX, then do some code. This has led to a rather strange looking creation of nested async functions. Also anytime I'm working with async functions, this ugly nesting comes up.
How can I avoid nesting functions when I really just want to wait for them each to complete? (I'm using jQuery if it helps)
function loadFilesAndDoStuff() {
$.get(firstFile, function(first_file_data) {
$.get(secondFile, function(second_file_data) {
$.get(thirdFile, function(third_file_data) {
someOtherAsyncFunction(function(combined_file_data) {
// do some stuff with the "combined_file_data".
});
});
});
});
}
Here are several different techniques with and without the use of deferreds. In all cases, all the ajax calls are launched and then some piece of code keeps track of when all the ajax calls have completed and collects the data from the calls as they complete so when the last one completes all the data is available.
You can launch all three ajax calls at once and just check in each completion function if they are all done yet, storing the results in a local variable until they are all done:
Or, you can put more of it in a common function and pass the array of filenames to the function:
Using Deferreds, you can do this:
Or, an even shorter version using the fact that deferreds save the arguments from the sucess handlers for each deferred:
Working demo of this last option: http://jsfiddle.net/jfriend00/5ppU4/
FYI, there's no magic inside of
$.when()
. If you look at the jQuery code for it, it is just keeping a counter of when the arguments passed to it are all done (similar to my first two options here). The main difference is that it's using the promise interface to the jqXHR object instead of knowledge that it's an ajax call. But conceptually, it's doing the same thing.Here's one more using a new object I've written for handling multiple deferreds.
The MultiDeferred code is a jQuery plug-in specifically written to handle notifying you when multiple deferreds are done and the code for it is here:
Create an array of each needed file, then loop through the array of files and call
$.get
each iteration, and have it call a combining function that will combine the data and do a count check, once count is reached call callback.