I need to wait until all my ajax functions are done, and then continue the exectution.
My particular case is that I need to translate some fields in a form before su
You can use callback
function translate(..., callback) {
$.ajax({
...
success:function(data) {
...
callback(data);
}
});
};
And pass your after ajax code to it
$("#form").submit(function() {
translatable_fields.each(function() {
translate(..., function(result){
if (!(this).hasClass('ready')) {
$.ajax({
//validation
success: function(data) {
if (data['isValid']) {
$("#form").addClass('ready');
$("#form").submit();
}
}
});
}
return true;
});
});
});
You can achieve this in a much neater fashion using the deferred
objects returned from a $.ajax
call. First you should get the translate()
function to return the deferred
:
function translate(...){
return $.ajax({
// settings...
});
});
Then you can put all those promises in to a single array:
var requests = [];
translatable_fields.each(function(){
requests.push(translate(...));
});
Then you can apply
that array to $.when
:
$.when.apply($, requests).done(function(schemas) {
console.log("All requests complete");
// do something...
});
No, you can't just loop like this: the callbacks would never get a chance to be called.
I would do something like this:
function translateAllFields(done) {
var requestsInProgress = 0, doneCalled = false;
translatable_fields.each(function () {
++requestsInProgress;
$.ajax({
//...
success: function (data) {
//...
$("#ajacCounter").val(parseInt($("#ajaxCounter").val()) - 1);
}
}).always(function () {
if (--requestsInProgress === 0) {
done();
doneCalled = true;
}
});
});
if (requestsInProgress === 0 && !doneCalled) {
// in case translatable_fields was empty
done();
}
}
and then:
$("#form").submit(function (e) {
if (!(this).hasClass('ready')) {
e.preventDefault();
e.stopPropagation();
translateAllFields(function() {
$.ajax({
//validation
success: function (data) {
if (data['isValid']) {
$("#form").addClass('ready');
$("#form").submit();
}
}
});
});
}
});
You can do this using deferred objects, but you do not need to use $.when.apply
with an array if you are only interested in the final completion.
Instead you can chain parallel promises using the pattern promise = $.when(promise, another promise)
Change your translate to return the Ajax promise:
function translate(...) {
...
return $.ajax({
...
});
}
and your promise loop simply becomes:
var promise; // Start with an undefined promise - which is the same as a resolved promise for $.when
translatable_fields.each(function() {
promise = $.when(promise, translate(...));
});
// Wait for all promises to complete
promise.done(function(){
// now do the final code after all the ajax calls complete
});
Notes:
$.when
, but the overhead is very small and the resulting code is quite simple.