web-dev-qa-db-fra.com

JQuery.each imbriqué () - continuer / interrompre

Considérez le code suivant:

    var sentences = [
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
        'Vivamus aliquet nisl quis velit ornare tempor.',
        'Cras sit amet neque ante, eu ultrices est.',
        'Integer id lectus id nunc venenatis gravida nec eget dolor.',
        'Suspendisse imperdiet turpis ut justo ultricies a aliquet tortor ultrices.'
    ];

    var words = ['ipsum', 'amet', 'elit'];

    $(sentences).each(function() {
        var s = this;
        alert(s);
        $(words).each(function(i) {
            if (s.indexOf(this) > -1)
            {
                alert('found ' + this);
                return false;
            }
        });
    });

La partie intéressante est les boucles imbriquées jQuery.each (). Selon la documentation , le retour de false sortira de la boucle (arrêt de l'exécution de la boucle - similaire à une instruction break normale de JavaScript), et le retour de non-false arrêtera l'itération en cours et continuera avec le itération suivante (similaire à une instruction continue JavaScript normale).

Je peux interrompre ou continuer un jQuery.each () seul, mais avec jQuery.each imbriqué, j'ai eu du mal à sortir de la boucle parent à partir de la boucle enfant. Je pouvais utiliser une valeur booléenne et la mettre à jour à chaque itération enfant, mais je me demandais s'il y avait un moyen plus simple.

J'ai mis en place n exemple sur jsFiddle si vous souhaitez jouer avec. Cliquez simplement sur le bouton "Test" pour exécuter l'exemple ci-dessus.

TLDR: Y a-t-il quelque chose qui ressemble à une continuation ou une interruption étiquetée dans le contexte de jQuery?

41
Ryan Kinal

Vous devriez le faire sans jQuery, ce n'est peut-être pas aussi "joli" mais il y a moins de choses et il est plus facile de faire exactement ce que vous voulez, comme ceci :

var sentences = [
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
    'Vivamus aliquet nisl quis velit ornare tempor.',
    'Cras sit amet neque ante, eu ultrices est.',
    'Integer id lectus id nunc venenatis gravida nec eget dolor.',
    'Suspendisse imperdiet turpis ut justo ultricies a aliquet tortor ultrices.'
];

var words = ['ipsum', 'amet', 'elit'];

for(var s=0; s<sentences.length; s++) {
    alert(sentences[s]);
    for(var w=0; w<words.length; w++) {
        if(sentences[s].indexOf(words[w]) > -1) {
            alert('found ' + words[w]);
            return;
        }
    }
}

Vous pouvez l'essayer ici . Je ne sais pas si c'est le comportement exact que vous recherchez, mais maintenant vous n'êtes pas dans une fermeture à l'intérieur d'une fermeture créée par le double .each() et vous pouvez return ou break quand vous le souhaitez dans ce cas.

22
Nick Craver

Il y a beaucoup de réponses ici. Et c'est vieux, mais c'est pour tous ceux qui viennent ici via google. Dans jQuery chaque fonction

return false; est comme break.

juste

return; est comme continue

Ceux-ci imiteront le comportement de pause et continueront.

92
Thihara

Comme indiqué dans la documentation jQuery http://api.jquery.com/jQuery.each/

return true dans jQuery.each est identique à un continue

return false est identique à un break

12
Serj Sagan

Il n'y a pas de moyen propre de le faire et comme @Nick mentionné ci-dessus, il pourrait être plus facile d'utiliser l'ancienne méthode de boucles car vous pouvez alors contrôler cela. Mais si vous voulez vous en tenir à ce que vous avez obtenu, vous pouvez gérer cela. Je suis sûr que j'obtiendrai de la chaleur pour celui-ci. Mais...

Une façon de faire ce que vous voulez sans instruction if est de déclencher une erreur et de boucler votre boucle avec un bloc try/catch:

try{
$(sentences).each(function() {
    var s = this;
    alert(s);
    $(words).each(function(i) {
        if (s.indexOf(this) > -1)
        {
            alert('found ' + this);
            throw "Exit Error";
        }
    });
});
}
catch (e)
{
    alert(e)
}

Ok, laissez la raclée commencer.

8
spinon

Le problème ici est que même si vous pouvez renvoyer false depuis le rappel .each, La fonction .each Elle-même renvoie l'objet jQuery. Vous devez donc renvoyer un faux aux deux niveaux pour arrêter l'itération de la boucle. De plus, comme il n'y a aucun moyen de savoir si le .each Interne a trouvé une correspondance ou non, nous devrons utiliser une variable partagée en utilisant une fermeture qui est mise à jour.

Chaque itération interne de words fait référence à la même variable notFound, il nous suffit donc de la mettre à jour lorsqu'une correspondance est trouvée, puis de la renvoyer. La fermeture externe a déjà une référence, elle peut donc break sortir si nécessaire.

$(sentences).each(function() {
    var s = this;
    var notFound = true;

    $(words).each(function() {
        return (notFound = (s.indexOf(this) == -1));
    });

    return notFound;
});

Vous pouvez essayer votre exemple ici .

7
Anurag

J'ai utilisé un modèle "d'évasion" pour cela:

$(sentences).each(function() {
    var breakout;
    var s = this;
    alert(s);
    $(words).each(function(i) {
        if (s.indexOf(this) > -1)
        {
            alert('found ' + this);
            return breakout = false;
        }
    });
    return breakout;
});

Cela fonctionne bien à n'importe quelle profondeur d'imbrication. breakout est un simple drapeau. Il restera undefined à moins que et jusqu'à ce que vous le définissiez sur false (comme je le fais dans ma déclaration de retour comme illustré ci-dessus). Tout ce que tu dois faire est:

  1. déclarez-le dans votre fermeture extérieure: var breakout;
  2. ajoutez-le à votre return false instruction (s): return breakout = false
  3. renvoyez la cassure dans vos fermetures extérieures.

Pas trop inélégant, non? ... fonctionne pour moi de toute façon.

5
joneit

Confirmez dans la documentation de l'API http://api.jquery.com/jQuery.each/ dites:

Nous pouvons rompre la boucle $ .each () à une itération particulière en faisant en sorte que la fonction de rappel renvoie false. Renvoyer une valeur non fausse équivaut à une instruction continue dans une boucle for; il sautera immédiatement à la prochaine itération.

et ceci est mon exemple http://jsfiddle.net/r6jqP/

(function($){
    $('#go').on('click',function(){
        var i=0,
            all=0;
        $('li').each(function(){
             all++;
             if($('#mytext').val()=='continue')return true;
             i++;
             if($('#mytext').val()==$(this).html()){
                 return false;
             }
        });
        alert('Iterazione : '+i+' to '+all);
    });
}(jQuery));
3
Leonardo Ciaccio

retour vrai ne fonctionne pas

retour faux travail

found = false;
query = "foo";

$('.items').each(function()
{
  if($(this).text() == query)
  {
    found = true;
    return false;
  }
});
3
misima

Malheureusement non. Le problème ici est que l'itération se produit à l'intérieur des fonctions, donc elles ne sont pas comme des boucles normales. La seule façon de "sortir" d'une fonction est de retourner ou de lever une exception. Donc oui, l'utilisation d'un drapeau booléen semble être le seul moyen raisonnable de "sortir" de la "boucle" extérieure.

3
casablanca