La funzione "each ()" di jQuery è sincrona?


131

considerare questo scenario per la convalida:

function validateForm (validCallback) {
   $('#first-name').add($('#last-name')).add($('#address')).each(function () {
      // validating fields and adding 'invalid' class to invalid fields.
   });
   // doing validation this way for almost 50 fields (loop over 50 fields)
   if ($('#holder .invalid').length == 0) {
       // submitting data here, only when all fields are validated.
   }
}

Ora, il mio problema è che il blocco if viene eseguito prima che i loop siano terminati. Mi aspettavo che il corpo di validateFormvenisse eseguito in modo sincrono, ma sembra che la each()funzione jQuery venga eseguita in modo asincrono. Ho ragione? Perché questo non funziona?


2
Che aspetto ha il codice di convalida? eachè sincrono, ma il codice all'interno potrebbe non essere ...
lonesomeday

1
eachstesso viene elaborato in modo sincrono. Stai iniziando un'operazione asincrona da solo all'interno del loop?
Jon,

3
problema simile qui ... come lo hai risolto?
sakthig,

È molto tempo fa, non ricordo. Ma so che le risposte mi hanno aiutato. Quindi, avrei potuto usare blocchi di codice asincroni nel mio codice di convalida (come provare a convalidare l'indirizzo usando una richiesta Ajax).
Saeed Neamati,

1
hmm .. l'ho risolto in questo modo .. stavo facendo "return false" all'interno di ogni funzione che non funzionava immagino .. ora sto mantenendo una bandiera all'interno di questa funzione e restituendo quella bandiera alla fine della convalida ..
sakthig

Risposte:


158

Sì, il eachmetodo jQuery è sincrono. Quasi TUTTO JavaScript è sincrono. Le uniche eccezioni sono AJAX, timer ( setTimeoute setInterval) e HTML5 Web Workers.
Il tuo problema è probabilmente da qualche altra parte nel tuo codice.


7

jQueryè puramente una libreria javascript. Tranne ajax, setTimeoute setIntervalnon c'è nulla che possa essere eseguito in modo asincrono JavaScript. Quindi eachviene sicuramente eseguito in modo sincrono. C'è sicuramente qualche errore js nel eachcodice di blocco. Dovresti dare un'occhiata nella console per eventuali errori.

In alternativa è possibile dare un'occhiata alla coda jQuery per eseguire qualsiasi funzione nella coda. Ciò assicurerà che la funzione in coda venga eseguita solo al termine dell'esecuzione del codice precedente.


7
ci sono anche promesse ... solo dicendo :)

6

Un altro motivo per porre questa domanda sarebbe che .each interromperà semplicemente l'iterazione quando la funzione (.each ()) restituisce false e una variabile aggiuntiva deve essere utilizzata per passare le informazioni "return false".

var all_ok=true;
$(selector).each(function(){
    if(!validate($(this))){
        all_ok=false; //this tells the outside world something went wrong
        return false; //this breaks the .each iterations, returning early
    }
});
if(!all_ok){
    alert('something went wrong');
}

2

Per me funziona come asincrono. Se funziona sincronizzato, perché funziona così:

var newArray = [];
$.each( oldArray, function (index, value){
        if($.inArray(value["field"], field) === -1){
            newArray.push(value["field"]);
        }
    }
);

//do something with newArray here doesn't work, newArray is not full yet

$.when.apply($, newArray).then(function() {
    //do something with newArray works!! here is full
});

2

return falsein .each()funzione interrompe solo il ciclo e il codice rimanente all'esterno del ciclo viene comunque eseguito. Quindi imposta un flag in .each()loop e controllalo al di fuori del loop.


1

Stesso problema. Quindi aggiusto in questo modo

var y = jQuery(this).find(".extra_fields");
for(var j in y)
{
    if( typeof  y[j] =='object')
    {
        var check = parseInt(jQuery(y[j]).val());
        if(check==0){
            jQuery(y[j]).addClass('js_warning');
            mes="Bạn vui lòng chọn đầy đủ các thuộc tính cho sản phẩm";
            done=false;
            eDialog.alert(mes);
            return false;
        }
    }

}

1

Ecco come lo faccio

 function getAllEventsIndexFromId(id) {
    var a;
    $.each(allEvents, function(i, val) {
        if (val.id == id) { a=i; }
    });
    return a;
 }

0

Ho avuto lo stesso problema. il mio $ .each era all'interno della funzione di successo della chiamata Ajax. ho reso la mia chiamata ajax sincrona aggiungendo async: falsee ha funzionato.


-9

Il metodo jQuery.each esegue il loop in modo sincrono, ma non è possibile garantire che eseguirà il ciclo tra gli articoli in un ordine specifico.


21
No, li attraverserà sempre nell'ordine in cui compaiono nel documento.
Abraham,

3
Dipende da cosa stai ripetendo. Ciascuno garantisce l'esecuzione dell'ordine dell'indice su un array, ma non fornisce garanzie per un oggetto (che dovrebbe essere ovvio).
Deadron,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.