Le chiamate AJAX vengono eseguite in modo asincrono quindi l'esecuzione del codice prosegue senza attendere la fine della chiamata AJAX. Se la chiamata AJAX è inserita in un ciclo le cose peggiorano perchè il tempo di esecuzione aumenta ma nel frattempo lo script prosegue.
Questo comportamento rende impossibile valutare una variabile che è stata modificata all'interno della chiamata AJAX
Esempio
Imposto una variabile la variabile count_error=0
prima del ciclo di chiamate AJAX, la incremento in caso di errori e la valuto alla fine del ciclo. Il seguente codice esegue le chiamate AJAX ma nel frattempo passa già alla valutazione diella variabile count_error
senza aspettare la risposta di AJAX, di conseguenza la variabile count_error
risulterà sempre "0".
var count_error = 0;//imposto la variabile
$(".some_class").each(function() {
setTimeout(function(){
$.ajax({
url: "/index.php",
method: 'POST',
data: {
// ....some data...
},
success: function(result) {
// actions if success
},
error: function() {
// actions if error occurs
count_error++; //incremento la variabile in caso di errori
}
});
}, 500);
});
//la valutazione della variabile count_error viene eseguita prima di attendere il risultato delle chiamate AJAX
if (count_error == 0) {
// no errors
} else {
//some errors
}
Soluzione
La soluzione consiste nell'aggiungere un oggetto Deferred
nel quale salvare le chiamate AJAX e aggiungere la funzione when
per iniziare la valutazione solo quando l'oggetto Deferred è terminato.
var count_error = 0;
var ajaxCalls = []; //crea un array di oggetti da popolare ad ogni ciclo da valutare alla fine del ciclo
$(".some_class").each(function() {
// Creazione di un Deferred object per ogni chiamata AJAX
var ajaxCall = $.Deferred();
ajaxCalls.push(ajaxCall);
setTimeout(function(){
$.ajax({
url: "/index.php",
method: 'POST',
data: {
// ....some data...
},
success: function(result) {
// actions if success
ajaxCall.resolve(); // Risolvi il Deferred object
},
error: function() {
count_error++;
ajaxCall.resolve(); // Risolvi il Deferred object anche in caso di errore
}
});
}, 500);
});
// Dopo che tutte le chiamate AJAX sono completate
$.when.apply($, ajaxCalls).done(function() {
if (count_error == 0) {
// no errors
} else {
//some errors
}
});
Commenti offerti da CComment