A função “each ()” do jQuery é síncrona?

131

considere este cenário para validar:

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

Agora, meu problema é que, o bloco if é executado antes que os loops sejam concluídos. Eu esperava que o corpo validateFormfosse executado de forma síncrona, mas parece que a each()função jQuery é executada de forma assíncrona. Estou certo? Por que isso não funciona?

Saeed Neamati
fonte
2
Como é o código de validação? eaché síncrono, mas o interior código pode não ser ...
lonesomeday
1
eachem si é processado de forma síncrona. Você está iniciando alguma operação assíncrona de dentro do loop?
Jon
3
problema semelhante aqui .. como você resolveu isso?
Sakthig
Faz muito tempo, não me lembro. Mas eu sei que as respostas me ajudaram. Portanto, eu poderia ter usado blocos de código assíncrono no meu código de validação (como tentar validar o endereço usando uma solicitação ajax).
Saeed Neamati
1
hmm .. eu resolvi dessa maneira .. eu estava fazendo "return false" dentro de cada função que não estava funcionando, eu acho .. agora estou mantendo uma flag dentro dessa função e retornando a flag no final da validação ..
sakthig

Respostas:

158

Sim, o eachmétodo jQuery é síncrono. Quase todo o JavaScript é síncrono. As únicas exceções são AJAX, timers ( setTimeoute setInterval) e HTML5 Web Workers.
Seu problema provavelmente está em outro lugar no seu código.

Abraão
fonte
7

jQueryé puramente uma biblioteca javascript. Exceto ajax, setTimeoute setIntervalnão há nada que possa ser executado de forma assíncrona JavaScript. Então eaché definitivamente executado de forma síncrona. Definitivamente, existe algum erro js dentro do eachcódigo de bloco. Você deve dar uma olhada no console quanto a erros.

Como alternativa, você pode dar uma olhada na fila do jQuery para executar qualquer função na fila. Isso garantirá que a função na fila seja executada apenas quando a execução do código anterior for concluída.

ShankarSangoli
fonte
7
há também promessas ... apenas dizendo :)
6

Outro motivo para fazer essa pergunta seria que .each simplesmente interromperá a iteração quando a função (.each ()) retornar false, e uma variável adicional deve ser usada para passar as informações "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');
}
Morg.
fonte
2

Para mim, funciona como assíncrono. Se funciona sincronizado, por que funciona assim:

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
fonte
2

return falseA .each()função in quebra apenas o loop, e o código restante fora do loop ainda é executado. Portanto, defina uma bandeira em .each()loop e verifique-a fora do loop.

M Hussain
fonte
1

Mesmo problema. Então eu corrijo assim

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
fonte
1

É assim que eu faço

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

Eu tive o mesmo problema. meu $ .each estava dentro da função de sucesso da chamada ajax. Eu fiz minha chamada ajax síncrona adicionando async: falsee funcionou.

Nilkamal Gotarne
fonte
-9

O método jQuery.each faz um loop de forma síncrona, mas você não pode garantir que ele percorrerá os itens em qualquer ordem específica.

Chris Pietschmann
fonte
21
Não, ele sempre passará por eles na ordem em que aparecem no documento.
Abraham
3
Depende do que você está repetindo. Cada um deles garante a execução da ordem do índice em uma matriz, mas não garante nenhum objeto (o que deve ser óbvio).
23713 Deadron