445 votes

comment arrêter le Javascript forEach ?

Je joue avec Node.js et Mongoose - j'essaie de trouver un commentaire spécifique dans un imbroglio de commentaires profonds avec une fonction récursive et des forEach dans. Existe-t-il un moyen d'arrêter Node.js forEach ? D'après ce que je comprends, chaque forEach l'itération est une fonction et je ne peux pas juste faire break seulement return mais cela n'arrêtera pas forEach .

function recurs(comment) {
    comment.comments.forEach(function(elem) {

        recurs(elem);

        //if(...) break;

    });
}

1120voto

uʍop ǝpısdn Points 16540

Vous ne pouvez pas rompre avec un forEach . Je peux penser à trois façons de le simuler, cependant.

1. La voie laide : passer un deuxième argument à forEach à utilisation comme contexte et y stocker un booléen, puis utiliser une balise if . Ça a l'air horrible.

2. La voie de la controverse : entourer le tout dans un try-catch bloque et lève une exception lorsque vous voulez vous arrêter. Cela semble assez mauvais et peut affecter les performances mais peuvent être encapsulés.

3. La manière amusante : utilisation every() .

['a', 'b', 'c'].every(function(element, index) {
  // Do your thing, then:
  if (you_want_to_break) return false
  else return true
})

Vous pouvez utiliser some() à la place, si vous préférez return true de se briser.

77 votes

+1, bien qu'il me semble plus naturel d'utiliser some() et return true quand tu veux casser.

30 votes

Ou plus élégamment, mettez return !you_want_to_break à l'intérieur de la boucle au lieu du bloc if..else. Cela permet de gagner deux lignes :-)

24 votes

every supporté partout sauf IE7 & 8 (j'ai dû vérifier, alors j'ai pensé que je devais partager)

64voto

Domenic Points 40761

Sortir de la Tableau#forEach n'est pas possible. (Vous pouvez inspecter le code source qui l'implémente dans Firefox sur la page liée, pour le confirmer).

Au lieu de cela, vous devriez utiliser un for boucle :

function recurs(comment) {
    for (var i = 0; i < comment.comments.length; ++i) {
        var subComment = comment.comments[i];
        recurs(subComment);
        if (...) {
            break;
        }
    }
}

(ou, si vous voulez être un peu plus malin à ce sujet et comment.comments[i] est toujours un objet :)

function recurs(comment) {
    for (var i = 0, subComment; subComment = comment.comments[i]; ++i) {
        recurs(subComment);
        if (...) {
            break;
        }
    }
}

0 votes

C'est possible en lançant à l'intérieur de la fonction forEach, comme l'indique la réponse acceptée.

5 votes

Bien sûr, mais utiliser des exceptions pour contrôler le flux du programme est une mauvaise pratique.

39voto

igor Points 642

Dans certains cas Array.some répondra probablement aux exigences.

0 votes

Cela devrait être la réponse canonique, car le traitement s'arrêtera dès qu'il aura trouvé le bon élément. Alors que forEach et every (tel que je le comprends) peut être piraté pour retourner vrai sur le premier élément qu'il trouve, il va toujours parcourir le tableau entier. Deuxièmement, Javascript n'effectue pas d'optimisation de queue et donc toutes les fonctions récursives sont intrinsèquement fragiles jusqu'à la sortie de ES6.

1 votes

Quel est le support du navigateur ?

0 votes

@imalhasarangaperera Ici vous pouvez trouver le support actuel du navigateur. developer.mozilla.org/fr/US/docs/Web/JavaScript/Référence/

31voto

zyklus Points 31683

Comme d'autres l'ont souligné, vous ne pouvez pas annuler une forEach boucle, mais voici ma solution :

ary.forEach(function loop(){
    if(loop.stop){ return; }

    if(condition){ loop.stop = true; }
});

Bien sûr, cela n'interrompt pas réellement la boucle, mais empêche l'exécution du code sur tous les éléments qui suivent le "break".

1 votes

J'aime bien celui-là. Je combinerais juste la dernière ligne à loop.stop = condition cependant. Cela ne devrait pas faire de différence car lorsqu'il est réglé sur true il ne sera plus exécuté.

2 votes

Utilisation astucieuse des expressions de fonctions nommées

14 votes

Je ne pense pas que cette solution soit une bonne idée. Imaginez que vous boucliez 10000 éléments et que votre condition s'arrête au deuxième élément, alors vous allez faire une itération inutile de 9998 fois pour rien. La meilleure approche consiste à utiliser some ou every .

-11voto

user2381380 Points 1

Pourquoi ne pas utiliser une simple déclaration ?

function recurs(comment){
comment.comments.forEach(function(elem){
    recurs(elem);
    if(...) return;
});

il retournera la fonction 'recurs'. Je l'utilise comme ceci. Bien que cela ne soit pas une rupture de forEach mais de la fonction entière, dans cet exemple simple, cela pourrait fonctionner.

0 votes

Vous ne pouvez pas retourner dans une boucle

1 votes

@Hazaart Bien que vous ne puissiez pas faire ça dans forEach vous pouvez retourner dans les boucles et la fonction se terminera sans autre itération de la boucle. (par exemple for (... in ...) , while etc.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X