Является ли функция jQuery «each ()» синхронной?

132

рассмотрите этот сценарий для проверки:

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

Теперь моя проблема в том, что блок if выполняется до завершения циклов. Я ожидал, что тело validateFormбудет выполняться синхронно, но кажется, что each()функция jQuery выполняется асинхронно. Я прав? Почему это не работает?

Саид Нямати
источник
2
Как выглядит код проверки? eachсинхронно, но код внутри может быть не ...
lonesomeday
1
eachсам обрабатывается синхронно. Вы начинаете какую-то собственную асинхронную операцию из цикла?
Джон
3
аналогичная проблема здесь .. как вы ее решили?
Сактиг
Это было давно, не помню. Но я знаю, что ответы мне помогли. Итак, я мог использовать блоки асинхронного кода в своем коде проверки (например, пытаться проверить адрес с помощью запроса ajax).
Саид Нямати
1
хм .. я решил это таким образом .. я делал "return false" внутри каждой функции, которая не работала, я думаю ... теперь я поддерживаю флаг внутри каждой функции и возвращаю этот флаг в конце проверки ..
sakthig

Ответы:

159

Да, eachметод jQuery синхронный. Почти ВСЕ JavaScript синхронны. Единственными исключениями являются AJAX, таймеры ( setTimeoutи setInterval) и веб-воркеры HTML5.
Вероятно, ваша проблема в другом месте вашего кода.

Авраам
источник
7

jQueryэто чисто библиотека javascript. За исключением случаев ajax, setTimeoutи setIntervalнет ничего , что может асинхронно выполняться в JavaScript. Так eachчто точно выполняется синхронно. Внутри eachкода блока определенно есть какая-то ошибка js . Вы должны проверить консоль на наличие ошибок.

В качестве альтернативы вы можете взглянуть на очередь jQuery для выполнения любой функции в очереди. Это гарантирует, что функция в очереди будет выполнена только после завершения предыдущего выполнения кода.

ShankarSangoli
источник
7
есть еще обещания ... просто говорю :)
6

Еще одна причина задать этот вопрос заключается в том, что .each просто остановит итерацию, когда функция (.each ()) вернет false, и необходимо использовать дополнительную переменную для передачи информации «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

Для меня это работает как асинхронно. Если работает синхронизация, почему так работает:

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
источник
2

return false.each()Функция in прерывает только цикл, а оставшийся код вне цикла по-прежнему выполняется. Итак, установите флаг в .each()цикле и проверьте его вне цикла.

М. Хуссейн
источник
1

Та же проблема. Так что я исправляю вот так

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
источник
1

Вот как я это делаю

 function getAllEventsIndexFromId(id) {
    var a;
    $.each(allEvents, function(i, val) {
        if (val.id == id) { a=i; }
    });
    return a;
 }
Miguel
источник
0

Я была такая же проблема. мой $ .each находился внутри функции успеха вызова ajax. Я сделал свой вызов ajax синхронным, добавив, async: falseи он сработал.

Нилькамал Готарне
источник
-9

Метод jQuery.each зацикливается синхронно, но вы не можете гарантировать, что он будет перебирать элементы в каком-либо определенном порядке.

Крис Питчманн
источник
21
Нет, он всегда будет проходить их в цикле в том порядке, в котором они указаны в документе.
Авраам
3
Это зависит от того, что вы повторяете. Каждый гарантирует выполнение порядка индексации в массиве, но не дает никаких гарантий для объекта (что должно быть очевидно).
Deadron