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?


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.


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.


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

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

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


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

}

1

Tak to robię

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

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.


-10

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


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.