I'm having an issue with using jQuery.when() to wait for multiple ajax requests to finish before calling another function.
Each ajax request will get JSON data, and looks something like this:
function loadData(arg){
var ajaxCall = $.ajax(
URL // depends on arg
)
.error( .... );
return ajaxCall;
}
When the request is called, the return value (ajaxCall) is added to a list called ajaxRequests.
ajaxRequests = [];
ajaxREquests.push(loadData(arg))
When all the requests have been made, I'm trying to pass ajaxRequests to $.when in order to wait for all requests to complete.
var defer = $.when.apply($, ajaxRequests);
defer.done(function(args){
for (var i=0; i<args.length; i++){
inst.loadData($.parseJSON(args[i].responseText));
}
inst.draw();
});
inst is an object that loads and draws graphs based on JSON data.
The problem is that it doesn't seem to be actually waiting for the requests to finish - args[i] is an object, but responseText is undefined when the code runs. If I save args[i] and access it later from the console, it works.
I suspect the problem is related to using .when with an arbitrary number of arguments, as all the examples I've seen on the web give it a pre-defined argument list.
I'm not sure if using apply was the right idea or not, but either way it doesn't work properly and behaves erratically (browser-dependent).
Any help would be greatly appreciated.
Please let me know if more information is required.
I'm using jQuery 1.5
Although Alex did indeed provide a solution to his problem, I found following it a bit difficult. I had an issue similar to his that I solved, and I wanted to share my solution for anyone else who needs to process a variable number of ajax requests.
// Array of requests
var requests = Array();
requests.push($.get('responsePage.php?data=foo'));
requests.push($.get('responsePage.php?data=bar'));
var defer = $.when.apply($, requests);
defer.done(function(){
// This is executed only after every ajax request has been completed
$.each(arguments, function(index, responseData){
// "responseData" will contain an array of response information for each specific request
});
});
In addition to Andy Corman's answer (I am yet unable to reply to a post, I think ...), if you only have one request, the response information will be passed directly to the defer.done - function as an argument; So you need to provide an if for that case:
// Array of requests
var requests = Array();
requests.push($.get('responsePage.php?data=foo'));
var defer = $.when.apply($, requests);
defer.done(function(){
// This is executed only after every ajax request has been completed
if (requests.length == 1)
// "arguments" will be the array of response information for the request
else
$.each(arguments, function(index, responseData){
// "responseData" will contain an array of response information for each specific request
});
});
I think I've worked it out now - the problem was in processing the returned arguments. .done was getting passed three arguments only - the response text, status and jqXHR object. I was expecting it to get passed the jqXHR object resulting from each query.
I've solved it by moving the callback code for each query to a separate function (i.e. the ajax call in loadData is now specifying a callback function which does the '.loadData(...)' call) and the only thing being done by the .done call is the inst.draw(). This seems to work fine: the individual callback's are each execute before .done().
I'm not sure if that's exactly how it's supposed to work, but it seems to be doing the job.
Try ajaxStart and ajaxStop, which have listeners for open ajax requests.
http://api.jquery.com/ajaxStart/ http://api.jquery.com/ajaxStop/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With