Czy funkcja jQuery „each ()” jest synchroniczna?

135

rozważ ten scenariusz do walidacji:

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.
   }
}

Mój problem polega na tym, że blok if jest wykonywany przed zakończeniem pętli. Spodziewałem się, że ciało programu validateFormbędzie wykonywane synchronicznie, ale wygląda na to, że each()funkcja jQuery jest wykonywana asynchronicznie. Czy mam rację? Dlaczego to nie działa?

Saeed Neamati
źródło
2
Jak wygląda kod weryfikacyjny? eachjest synchroniczny, ale kod wewnątrz może nie być ...
lonesomeday
1
eachsama jest przetwarzana synchronicznie. Czy rozpoczynasz jakąś własną operację asynchroniczną z wnętrza pętli?
Jon,
3
podobny problem tutaj… jak go rozwiązałeś?
święto
To było dawno temu, nie pamiętam. Ale wiem, że odpowiedzi mi pomogły. Mogłem więc użyć bloków kodu asynchronicznego w moim kodzie walidacyjnym (na przykład próbując zweryfikować adres za pomocą żądania AJAX).
Saeed Neamati
1
hmm .. rozwiązałem to w ten sposób ... robiłem "return false" wewnątrz każdej funkcji, która chyba nie działała .. teraz utrzymuję flagę wewnątrz każdej funkcji i
zwracam

Odpowiedzi:

161

Tak, eachmetoda jQuery jest synchroniczna. Prawie WSZYSTKIE JavaScript są synchroniczne. Jedynymi wyjątkami są AJAX, timery ( setTimeouti setInterval) oraz HTML5 Web Workers.
Twój problem jest prawdopodobnie gdzieś w kodzie.

Abraham
źródło
8

jQueryjest czysto biblioteką javascript. Z wyjątkiem ajax, setTimeouti setIntervalnie ma nic, co można wykonywane asynchronicznie JavaScript. Więc eachjest zdecydowanie wykonywane synchronicznie. Zdecydowanie w eachkodzie blokowym jest błąd js . Powinieneś przejrzeć konsolę pod kątem jakichkolwiek błędów.

Alternatywnie możesz rzucić okiem na kolejkę jQuery, aby wykonać dowolną funkcję w kolejce. Zapewni to, że funkcja umieszczona w kolejce zostanie wykonana dopiero po zakończeniu poprzedniego wykonywania kodu.

ShankarSangoli
źródło
7
są też obietnice ... tylko mówię :)
7

Innym powodem, dla którego warto zadać to pytanie, byłoby to, że .each po prostu zatrzyma iterację, gdy funkcja (.each ()) zwróci fałsz, a do przekazania informacji „return false” należy użyć dodatkowej zmiennej.

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');
}
Morg.
źródło
3

U mnie działa asynchronicznie. Jeśli działa, zsynchronizuj, dlaczego działa tak:

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
});
Tuitx
źródło
2

return falsein .each()function przerywa tylko pętlę, a pozostały kod poza pętlą nadal jest wykonywany. Więc ustaw flagę w .each()pętli i sprawdź ją poza pętlą.

M Hussain
źródło
1

Taki sam problem. Więc naprawiam w ten sposób

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;
        }
    }

}
user3027521
źródło
1

Tak to robię

 function getAllEventsIndexFromId(id) {
    var a;
    $.each(allEvents, function(i, val) {
        if (val.id == id) { a=i; }
    });
    return a;
 }
Miguel
źródło
0

Miałem ten sam problem. mój $ .each znajdował się w funkcji sukcesu wywołania ajax. Zrobiłem moje wywołanie Ajax synchronicznie, dodając async: falsei zadziałało.

Nilkamal Gotarne
źródło
-10

Metoda jQuery.each zapętla się synchronicznie, ale nie można zagwarantować, że przejdzie przez elementy w określonej kolejności.

Chris Pietschmann
źródło
21
Nie, zawsze będzie je przeglądać w kolejności, w jakiej pojawiają się w dokumencie.
Abraham
3
To zależy od tego, nad czym iterujesz. Każdy gwarantuje wykonanie indeksu w tablicy, ale nie daje żadnych gwarancji dla obiektu (co powinno być oczywiste).
Deadron,