2009-11-04 2 views
5

Sto eseguendo una convalida sui dati del modulo, in modo tale che quando qualcuno preme il pulsante di invio controlla prima i contenuti del modulo. Un numero di campi (potrebbe essere zero, potrebbe essere più di uno, a seconda della pagina) hanno cose come codici univoci che richiedono prima il controllo con il server. Sto eseguendo una richiesta asincrona al server, che risponde semplicemente 'ok' o 'taken' per ogni campo. Se uno qualsiasi dei campi ha errori, la pagina non viene inviata.jQuery AJAX: raccolta di più risultati asincroni

Da un lato, questo dovrebbe essere asincrono: dovrebbe continuare a convalidare il resto dei campi del modulo mentre quella richiesta è inattiva, compreso l'attivazione di altre richieste. Se la chiamata viene effettuata in modo sincrono, rallenta visibilmente il feedback sui campi successivi.

D'altra parte, desidero assicurarmi che tutte le richieste di convalida siano ritornate (o scadute) prima di rispondere sì o no al metodo validate() e consentire al submit di procedere o meno. Pertanto, se sono necessari due campi che richiedono la convalida, il metodo validate() deve attivare queste due richieste AJAX, elaborare il resto dei campi e quindi attendere fino a quando queste due richieste non sono tornate prima di tornare definitivamente.

Probabilmente riuscirò a farlo con qualche brutta soluzione homebaked (probabilmente coinvolgendo una serie di ID casuali che rappresentano le richieste in corso o qualcosa del genere), ma prima di farlo c'è qualche funzione incorporata, plugin o tecnica standard che dovrei essere usando invece?


Chiarimento

Quello che penso che ho bisogno è quello di rendere il codice di attesa per il risultato da uno o più asincrone le richieste prima di procedere con un metodo. Questo non è lo stesso di un callback, perché il risultato del metodo dipende dal risultato delle richieste. Non è la stessa di una richiesta sincrona perché potrebbero esserci più di una di esse.

sto usando questo per controllare il modulo prima di inviarlo:

$("form").submit(function() { 
    return validate($(this)); 
}); 

Se il metodo validate() restituisce false, allora la forma non inviare. validate() elimina tutti i campi che non sono accettati. Per i campi normali, validate() sembra qualcosa di simile (versione notevolmente semplificata, senza il feedback):

function validate(form) { 
    resetWarnings(form); 
    var ok = true; 

    // required fields 
    form.find("input.required").each(function() { 
     var field = $(this); 
     if (field.val() === "") { 
      ok = false; 
     } 
     return this; // meaningless in this case but a good habit to keep 
    }); 

    // fields that matches a pattern 
    form.find("input.pattern").each(function() { 
     var field = $(this); 
     var pattern = field.data("pattern"); 
     if (!field.val().match(pattern)) { 
      ok = false; 
     } 
     return this; 
    }); 

    // various other rules for other sorts of field 
    ... 

    return ok; 
} 

Per i campi di AJAX è più simile a questo:

form.find("input.lookup").each(function() { 
     var field = $(this); 
     var url = field.data("lookup"); 
     $.ajax({ 
      url: url, 
      data: { code: field.val() }, 
      success: function (result) { 
       if (result === "taken") { 
        ok = false; 
       } 
      } 
     } 
    }); 

Ma, naturalmente, validate() è già finito prima il metodo di successo è chiamato. Quindi, se riesco a farlo attendere fino a quando l'ajax non è stato completato (sia successo che errore) prima di tornare, posso ottenere il risultato giusto e interrompere la presentazione del modulo. E se ho fatto l'ajax sincrono, allora l'intero metodo si ferma finché non è finito, il che è sbagliato.


ulteriori riflessioni

Dato modello di threading di Javascript (cioè nessuno), è quello che sto chiedendo tecnicamente impossibile?

risposta

1

Se ho capito bene, stai volendo controllare che i valori (1 ..*) inseriti in un modulo sono unici, una volta che l'utente preme il pulsante di invio prima di eseguire il post sul modulo. In tal caso, creerei un array JSON di campi e valori e invialo tutto in una volta, quindi stai solo aspettando una risposta. Questo dovrebbe essere abbastanza semplice usando la funzione jQuery 'each' e usando jQuery ajax.

È quindi possibile controllare il singolo risultato prima di inviare il modulo.

Probabilmente è ovvio, ma assicurati di ripetere lo stesso server di convalida dopo aver postato per evitare condizioni di gara con altri utenti.

È possibile convalidare singoli campi mentre l'utente completa il modulo e archiviare il risultato, ma questo sarebbe significativamente più chiacchierone (per motivi di scalabilità dovresti considerare la larghezza di banda) e ti esponi a una maggiore possibilità di mancata convalida lato server .

+0

Non è una sequenza di campi unici identici, ma la possibilità che più di un campo su un modulo abbia bisogno di controllo sul lato server - a URL diversi, rispetto a controlli diversi. In realtà, il bit multiplo non è ciò che è importante: sta facendo in modo che il metodo validate() attenda un risultato asincrono. L'unica ragione per cui sottolineo che potrebbe esserci più di un campo è che fare una singola chiamata sincrona non è una risposta valida. –

+0

Vedi chiarimenti. –

+0

Non sono sicuro di quello che sto chiedendo è possibile. Convalidare i campi mentre l'utente completa il modulo potrebbe finire per essere l'unico modo. –

0

Come sull'utilizzo .ajaxStop:

$(document).ajaxStop(function() { 
    $(this).unbind("ajaxStop"); 
    // run validate method here 
    }); 
    //run asynchronous validations here 

noti che UNBIND è necessaria se validate() si comporta una chiamata AJAX.

3

Con jQuery 1.5+ il modo migliore per raccogliere i dati dei risultati da più richieste asincrone è utilizzare gli oggetti rinviati che rappresentano queste richieste con i loro stati e la funzione wrapper $ .when (...). Then (allRequestsCompleteCallback(), someRequestFailedCallback())

Questo aiuta a evitare l'uso di più funzioni di callback annidate, rendendo il codice molto più pulito e più facile da mantenere.

JavaScript/jQuery esempio:

function ajax1() { return $.ajax({ url: 'server1.php' }) } 
function ajax2() { return $.ajax({ url: 'server2.php' }) } 

$.when(ajax1(), ajax2()).then(
    function() { 
     // ajax1 AND ajax2 succeeded 
    }, 
    function() { 
     // ajax1 OR ajax2 succeeded 
    } 
); 

Verificare la presenza di ulteriori documenti e gli esempi qui:

+0

C'è un modo per farlo senza sapere in anticipo quanti oggetti differiti avrai? Ad esempio quando le richieste multiple sono dovute alla suddivisione di una grande serie di lunghezze sconosciute in blocchi di lunghezza costante? – learn2day