2010-09-14 3 views
9

Sto utilizzando le schede dell'interfaccia utente jQuery in cui ogni scheda ha un modulo diverso. Dopo che l'utente ha inserito varie parti di dati, inviano l'intera serie di schede in modo che ogni scheda venga inviata al server in modo asincrono. Funziona bene e non ho problemi qui.Attendere la chiamata AJAX (POST) per terminare

Tuttavia, dove mi imbatto in un problema è che l'ultimo modulo che inserisco deve succedere DOPO che tutti gli altri post sono completi. idea generale è simile a questo:

postForm(0, "#Form1"); 
postForm(1, "#Form2"); 
postForm(2, "#Form3"); 
postForm(3, "#Form4"); 
$.post('Project/SaveProject', function (data) { 
    $('<div class="save-alert">The current project has been saved.</div>') 
    .insertAfter($('#tabs')) 
    .fadeIn('slow') 
    .animate({ opacity: 1.0 }, 3000) 
    .fadeOut('slow', function() { 
     $(this).remove(); 
    }); 
}); 

La funzione postForm fa un po 'di elaborazione e poi effettua una chiamata AJAX .post $. L'ultimo $ .post eseguito qui (su 'Project/SaveProject') deve attendere fino a quando questi altri post sono completati. Qual è il modo migliore per farlo?

risposta

14

si può semplicemente utilizzare l'evento .ajaxStop() che viene generato quando tutti gli altri posti AJAX finire, supponendo che si sta facendo nessun altro AJAX funziona allora, in questo modo:

postForm(0, "#Form1"); 
postForm(1, "#Form2"); 
postForm(2, "#Form3"); 
postForm(3, "#Form4"); 
$(document).ajaxStop(function() { 
    $.post('Project/SaveProject', function (data) { 
    $('<div class="save-alert">The current project has been saved.</div>') 
    .insertAfter($('#tabs')) 
    .fadeIn('slow') 
    .animate({ opacity: 1.0 }, 3000) 
    .fadeOut('slow', function() { 
     $(this).remove(); 
    }); 
    }); 
    $(this).unbind('ajaxStop'); 
}); 

.ajaxStop() incendi quando tutto richieste AJAX che sono in esecuzione completa, in modo che sarà solo fuochi quando tutte questi posti sono tornati, jQuery mantiene un conteggio interno ($.active, $.ajax.active in jQuery 1.5) per determind quanti simultanea re AJAX le missioni sono eccezionali ... quando torna a 0 questo evento si attiva.

Questo approccio consente di eseguire contemporaneamente gli altri moduli di invio e di eseguire il modulo finale appena possibile.

+0

Grazie per aver menzionato '$ .ajax.active' in jQuery 1.5! – Edgar

2

richiamate:

Definire postForm di prendere una richiamata:

function postForm(ind, id, callback) 
{ 
    // ... 
    $.post(url, function() 
    { 
    // ... 
    callback(); 
    }); 
} 

Poi fare qualcosa di simile alla seguente. Puoi usare la ricorsione per scriverla in un modo meno hard-coded, che potrebbe essere particolarmente utile se ci sono più forme.

postForm(0, "#Form1", function() 
{ 
    postForm(1, "#Form2", function() 
    { 
     postForm(2, "#Form3", function() 
     { 
      postForm(3, "#Form4", function() 
      { 
       $.post('Project/SaveProject', function (data) { 
        $('<div class="save-alert">The current project has been saved.</div>') 
         .insertAfter($('#tabs')) 
         .fadeIn('slow') 
         .animate({ opacity: 1.0 }, 3000) 
         .fadeOut('slow', function() { 
          $(this).remove(); 
         }); 
       }); 
      }); 
     }); 
    }); 
}); 
+0

Grazie per la risposta. Inizialmente l'avevo considerato, ma poi ho deciso che era un po 'troppo ingombrante con cui lavorare. (+1) – JasCav

0

Il problema con ajaxStop è che si attiva ogni volta che viene eseguito qualsiasi ajax. Un'alternativa sta attuando il metodo proprio stack in questo modo:

var stack = [] 
postForm(var1, var2){ 
    stack.push(1); 
    //Do postForm stuff 
    stack.pop(); 
    if (stack == undefined){ 
     //Call the last post method 
    } 
} 
postForm(0, "#Form1"); 
postForm(1, "#Form2"); 
postForm(2, "#Form3"); 
postForm(3, "#Form4"); 
$.post('Project/SaveProject', function (data) { 
    $('<div class="save-alert">The current project has been saved.</div>') 
    .insertAfter($('#tabs')) 
    .fadeIn('slow') 
    .animate({ opacity: 1.0 }, 3000) 
    .fadeOut('slow', function() { 
     $(this).remove(); 
    }); 
}); 
+0

'ajaxStop()' si attiverà solo quando * tutte * le richieste AJAX saranno completate, e lo interromperò la prima volta che viene eseguito, puoi approfondire come questo potrebbe essere un problema? Anche il tuo esempio non funzionerà, perché 'stack' sarà un array vuoto, non' indefinito' :) –

+0

Non ho visto il separatore in basso lì, ci scusiamo per questo. A seconda dell'app, ci possono essere molte chiamate ajax che volano in giro, e in situazioni in cui hai bisogno di controllo assoluto farei il mio stack di chiamate per il mio flusso di lavoro.Naturalmente, il tuo codice funziona anche (almeno se non ci sono chiamate Ajax in precedenza nell'applicazione, dove dovresti definire il gestore nel metodo postForm) – pederOverland

+0

Non sto legando il gestore finché questo batch di richieste non è sparato entrambi :) –

4

Si può sempre fare tutti i messaggi sincrono usando qualcosa come


$.ajax({ 
    type: "POST",  
    async: false, 
    url: "", 
    ... 

ovviamente andrei essere il più veloce, ma non risolve il problema se $ (documento) .ajaxStop non è un'opzione

+0

Questo non funziona più, restituisce questo messaggio: "XMLHttpRequest sincrono sul thread principale è deprecato a causa dei suoi effetti dannosi per l'esperienza dell'utente finale." – di3sel