I've got a particular function I want to run once, and only after the pletion of several AJAX requests.
My current solution looks a bit like this:
function doWork() {
//This is the function to be run once after all the requests
}
//some tracking/counting variables
var ajaxDoneCounter = 0;
var numOfAjaxRequests = 5;
var workDone = false;
function doWorkTrigger() {
ajaxDoneCounter++;
if( !workDone && ajaxDoneCounter >= numOfAjaxRequests ) {
workDone = true;
doWork();
}
}
// ...
//and a number of ajax requests (some hidden within functions, etc)
//they look something like this:
$.ajax({
url: "",
dataType: "json",
success: function( data ) {
//load data in to variables, etc
doWorkTrigger();
}
});
One obvious pitfall in the above is that any AJAX call that is not successful will not increment ajaxDoneCount
and so doWork()
will probably never be called. I can get around that using the error
callback in inside any $.ajax
, so that doesn't worry me too much.
What I want to know is whether the above is safe and/or good practice?
Is there a trick I've missed, or any thing else that might work better?
I've got a particular function I want to run once, and only after the pletion of several AJAX requests.
My current solution looks a bit like this:
function doWork() {
//This is the function to be run once after all the requests
}
//some tracking/counting variables
var ajaxDoneCounter = 0;
var numOfAjaxRequests = 5;
var workDone = false;
function doWorkTrigger() {
ajaxDoneCounter++;
if( !workDone && ajaxDoneCounter >= numOfAjaxRequests ) {
workDone = true;
doWork();
}
}
// ...
//and a number of ajax requests (some hidden within functions, etc)
//they look something like this:
$.ajax({
url: "http://www.example.",
dataType: "json",
success: function( data ) {
//load data in to variables, etc
doWorkTrigger();
}
});
One obvious pitfall in the above is that any AJAX call that is not successful will not increment ajaxDoneCount
and so doWork()
will probably never be called. I can get around that using the error
callback in inside any $.ajax
, so that doesn't worry me too much.
What I want to know is whether the above is safe and/or good practice?
Is there a trick I've missed, or any thing else that might work better?
- 1 Its what I would have suggested you do from reading the problem description. I'm not sure "I can't think of anything better" is a suitable "answer" though so just menting instead. ;-) – Chris Commented Aug 4, 2010 at 11:58
3 Answers
Reset to default 6Update: Since jQuery 1.5, deferred objects [docs] provide a cleaner solution. Have a look at an example here.
I would use .ajaxComplete()
, it will be triggered whenever an Ajax call pleted (success or error):
var numOfAjaxRequests = 5;
$(document).ajaxComplete(function() {
numOfAjaxRequests--;
if(!numOfAjaxRequests) {
doWork();
}
});
Then you don't have to edit every Ajax request.
You could even use .ajaxSend()
to get notified of starting Ajax requests, instead of hardcoding it (but I am not sure whether this really works, maybe you will experience race conditions):
var numOfAjaxRequests = 0;
$(document).ajaxSend(function() {
numOfAjaxRequests++;
});
I think you should use plete(XMLHttpRequest, textStatus)
ajax event instead of success(data, textStatus, XMLHttpRequest).
According to jQuery help:
plete(XMLHttpRequest, textStatus)
A function to be called when the request finishes (after success and error callbacks are executed). The function gets passed two arguments: The XMLHttpRequest object and a string describing the status of the request. This is an Ajax Event.
I don't know enough about JavaScript internals, but there is a danger that the operation:
ajaxDoneCounter++;
is not atomic. If that is the case, then this could be subject to a race condition.