La fonction jQuery «each ()» est-elle synchrone?

132

considérez ce scénario pour valider:

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

Maintenant, mon problème est que, le bloc if est exécuté avant que les boucles ne soient terminées. Je m'attendais à ce que le corps de validateFormsoit exécuté de manière synchrone, mais il semble que la each()fonction jQuery soit exécutée de manière asynchrone. Ai-je raison? Pourquoi ça ne marche pas?

Saeed Neamati
la source
2
À quoi ressemble le code de validation? eachest synchrone, mais le code à l'intérieur n'est peut-être pas ...
lonesomeday
1
eachlui-même est traité de manière synchrone. Lancez-vous votre propre opération asynchrone depuis l'intérieur de la boucle?
Jon
3
problème similaire ici .. comment l'avez-vous résolu?
sakthig
C'est il y a longtemps, je ne m'en souviens plus. Mais je sais que les réponses m'ont aidé. Donc, j'ai peut-être utilisé des blocs de code asynchrone dans mon code de validation (comme essayer de valider l'adresse à l'aide d'une requête ajax).
Saeed Neamati
1
hmm .. je l'ai résolu de cette façon .. je faisais "return false" à l'intérieur de chaque fonction qui ne fonctionnait pas je suppose .. maintenant je maintiens un drapeau à l'intérieur de chaque fonction et le retourne à la fin de la validation ..
sakthig

Réponses:

159

Oui, la eachméthode jQuery est synchrone. Presque TOUT JavaScript est synchrone. Les seules exceptions sont AJAX, les minuteries ( setTimeoutet setInterval) et les Web Workers HTML5.
Votre problème se situe probablement ailleurs dans votre code.

Abraham
la source
7

jQueryest purement une bibliothèque javascript. Sauf ajax, setTimeoutet setIntervalil n'y a rien qui puisse s'exécuter de manière asynchrone dans JavaScript. Donc eachest définitivement exécuté de manière synchrone. Il y a certainement une erreur js dans le eachcode de bloc. Vous devriez jeter un oeil dans la console pour toute erreur.

Vous pouvez également jeter un œil à la file d' attente jQuery pour exécuter n'importe quelle fonction de la file d'attente. Cela garantira que la fonction en file d'attente ne sera exécutée que lorsque l'exécution du code précédent sera terminée.

ShankarSangoli
la source
7
il y a aussi des promesses ... il suffit de dire :)
6

Une autre raison de se poser cette question serait que .each arrêtera simplement l'itération lorsque la fonction (.each ()) retourne false, et qu'une variable supplémentaire doit être utilisée pour transmettre les informations "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.
la source
2

Pour moi, cela fonctionne comme asynchrone. Si cela fonctionne synchronisé, pourquoi cela fonctionne comme ça:

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
la source
2

return falsein .each()function rompt la boucle uniquement, et le code restant en dehors de la boucle s'exécute toujours. Mettez donc un drapeau en .each()boucle et vérifiez-le en dehors de la boucle.

M Hussain
la source
1

Même problème. Alors je répare comme ça

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
la source
1

C'est comme ça que je fais

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

J'ai eu le même problème. mon $ .each était dans la fonction de succès de l'appel ajax. J'ai rendu mon appel ajax synchrone en ajoutant async: falseet cela a fonctionné.

Nilkamal Gotarne
la source
-9

La méthode jQuery.each effectue une boucle de manière synchrone, mais vous ne pouvez pas garantir qu'elle parcourra les éléments dans un ordre spécifique.

Chris Pietschmann
la source
21
Non, il les parcourra toujours dans leur ordre d'apparition dans le document.
Abraham du
3
Cela dépend de ce que vous répétez. Chacun garantit l'exécution de l'ordre d'index sur un tableau mais ne donne aucune garantie pour un objet (ce qui devrait être évident).
Deadron