¿La función jQuery "each ()" es síncrona?

131

considere este escenario 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.
   }
}

Ahora, mi problema es que el bloque if se ejecuta antes de que finalicen los bucles. Esperaba que el cuerpo de validateFormse ejecutara sincrónicamente, pero parece que la each()función jQuery se ejecuta de forma asincrónica. Estoy en lo cierto? ¿Por qué esto no funciona?

Saeed Neamati
fuente
2
¿Cómo se ve el código de validación? eaches síncrono, pero el código dentro podría no ser ...
lonesomeday
1
eachse procesa sincrónicamente. ¿Está comenzando alguna operación asíncrona propia desde dentro del bucle?
Jon
3
problema similar aquí ... ¿cómo lo resolvió?
sakthig
Hace mucho tiempo, no me acuerdo. Pero sé que las respuestas me ayudaron. Por lo tanto, podría haber utilizado bloques de código asíncrono en mi código de validación (como intentar validar la dirección usando una solicitud ajax).
Saeed Neamati
1
hmm ... lo resolví de esta manera ... estaba haciendo "return false" dentro de cada función que no funcionaba, supongo ... ahora mantengo una bandera dentro de cada función y
devuelvo

Respuestas:

158

Sí, el eachmétodo jQuery es sincrónico. Casi TODO JavaScript es sincrónico. Las únicas excepciones son AJAX, temporizadores ( setTimeouty setInterval) y HTML5 Web Workers.
Su problema probablemente esté en otro lugar de su código.

Abrahán
fuente
7

jQueryes puramente una biblioteca javascript. Excepto ajax, setTimeouty setIntervalno hay nada que pueda ejecutarse asincrónicamente JavaScript. Entonces eachdefinitivamente se ejecuta sincrónicamente. Definitivamente hay algún error js dentro del eachcódigo de bloque. Debes echar un vistazo en la consola por cualquier error.

Alternativamente, puede echar un vistazo a la cola jQuery para ejecutar cualquier función en la cola. Esto asegurará que la función en cola se ejecutará solo cuando se complete la ejecución del código anterior.

ShankarSangoli
fuente
77
también hay promesas ... solo diciendo :)
6

Otra razón para hacer esa pregunta sería que .each simplemente detendrá la iteración cuando la función (.each ()) devuelva false, y se debe usar una variable adicional para pasar la información "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
fuente
2

Para mí funciona como asíncrono. Si funciona la sincronización, por qué funciona así:

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

return falseLa .each()función in solo rompe el ciclo, y el código restante fuera del ciclo aún se ejecuta. Por lo tanto, establezca una bandera en .each()bucle y verifíquela fuera del bucle.

M Hussain
fuente
1

El mismo problema. Así que lo arreglo así

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

}
usuario3027521
fuente
1

Así es como lo hago

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

Tuve el mismo problema. my $ .each estaba dentro de la función de éxito de la llamada ajax. Hice mi llamada ajax sincrónica agregando async: falsey funcionó.

Nilkamal Gotarne
fuente
-9

El método jQuery.each se repite sincrónicamente, pero no puede garantizar que recorra los elementos en un orden específico.

Chris Pietschmann
fuente
21
No, siempre los recorrerá en el orden en que aparecen en el documento.
Abraham
3
Depende de lo que estés iterando. Cada uno garantiza la ejecución de la orden de índice en una matriz, pero no garantiza un objeto (lo que debería ser obvio).
Deadron