Reputation: 83033
I'm iterating through a group of html elements using a jquery each
. On each iteration I invoke a get
. I want to keep track of the successful gets and output a count at the end.
var numSuccessful = 0;
$('.mySelector').each(function(){
$.get('/myCfc.cfc?method=doSomething&id=' + $(this).attr('id'),
function(data){
numSuccessful++;
});
});
alert(numSuccessful + ' successful');
The problem with this code is that the each method starts off all the get calls and then continues to the alert before completing the gets - and before the numSuccessful variable is updated. On a test run, I ended up with "0 successful" instead of "4 successful" because the alert executed too quickly. How can I get the code to wait till all the gets complete before continuing? Is there a success callback for the entire "each" statement?
Upvotes: 4
Views: 286
Reputation: 11812
You could use the promise returned by $.ajax
to setup a flexible callback queue like this:
var requests = []; //Array containing all the ajax calls
for (var i = 0; i < 9; i++) {
requests.push(
$.ajax({
url: '/echo/html', //this is because of jsfiddle.net
type: 'post', //this one too
success: function() {
//whatever
}
}));
}
$.when.apply($, requests).then(function() { //.apply is needed as we want to pass an Array
//called when all requests are done
}).fail(function(){ //this will be triggered when one of the requests fails
//error handling can go here
});
See this working fiddle and read about .when()
and .then
In your case that would end up in:
var numSuccessful = 0;
var requests = $.makeArray($('.mySelector').map(function(){
return $.ajax({
url: '/myCfc.cfc?method=doSomething&id=' + this.id,
type: 'GET'
}).done(function(){
numSuccessful++;
});
}));
$.when.apply($, requests).then(function() {
alert(numSuccessful + ' successful');
});
Upvotes: 1
Reputation: 836
Just replace $.get
with $.ajax
and set async
setting to false.
$.ajax({
url : '/myCfc.cfc',
data : { 'method' : 'doSomething' , 'id' : $(this).attr('id') },
async : false,
success : function(data){
numSuccessful++;
}
});
By doing this script will wait until it will get response.
Upvotes: 1
Reputation: 144659
You can use a recursive function, try the following:
var num = 0;
var $ms = $('.mySelector');
function go() {
$.get('/myCfc.cfc?method=doSomething&id='+$ms.eq(num).attr('id'),
function(data){
num++;
if ((num-1) == $ms.length) callback(); else go();
}).error(callback)
}
function callback(){
alert(num)
}
go()
Upvotes: 1
Reputation: 26753
var numSuccessful = 0;
var totalSelectors = $('#mySelector').length;
$('#mySelector').each(function(){
$.get('/myCfc.cfc?method=doSomething&id=' + $(this).attr('id'),
function(data){
numSuccessful++;
if(!totalSelectors--) doneSelectors();
});
});
function doneSelectors() {
alert(numSuccessful + ' successful');
}
Note: The above function does NOT work properly! The $.get()
does not notify on errors, so if you get any errors the final function will never run.
Instead you need to convert it to use the $.ajax()
function. And define both success and failure callbacks. If you need help doing that let me know.
Upvotes: 0