Logo Informatizzati

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