Angular JS break ForEach


256

J'ai une boucle foreach angulaire et je veux rompre la boucle si je correspond à une valeur. Le code suivant ne fonctionne pas.

angular.forEach([0,1,2], function(count){
  if(count == 1){
    break;
  }
});

Comment puis-je l'obtenir?


1
Je ne comprends pas pourquoi vous ne trouvez pas simplement la valeur au lieu d'aller dans une boucle. Peut-être que l'exemple que vous avez donné ne raconte pas toute l'histoire, mais je préfère faire ce que @Aman a dit ci-dessous. Pourquoi entrer dans la boucle comme mentionné ci-dessous et exécuter une vérification à chaque fois que certains () le font de manière plus élégante. N'oubliez pas que si vous traitez javascript comme un langage fonctionnel, il ne devrait pas être utile d'utiliser ces structures de contrôle pour / while / break. C'est pourquoi foreach, find, some, etc exist
Adrian Rodriguez

Réponses:


264

Il n'y a aucun moyen de le faire. Voir https://github.com/angular/angular.js/issues/263 . Selon ce que vous faites, vous pouvez utiliser un booléen pour ne pas entrer dans le corps de la boucle. Quelque chose comme:

var keepGoing = true;
angular.forEach([0,1,2], function(count){
  if(keepGoing) {
    if(count == 1){
      keepGoing = false;
    }
  }
});

45
Je préfère simplement ajouter un !keepGoing && return;en haut de la fonction, moins de code.
Andrew Joslin

46
Ce ne sont pas les meilleures pratiques, ici la boucle angulaire forEach ne se rompt jamais, et il n'y a rien à casser angular.forEach. La boucle native pour est environ 90% plus rapide qu'angular.forEach. Il est donc préférable d'utiliser la boucle for native lorsque vous souhaitez rompre la correspondance de condition. Merci
Nishchit Dhanani

xcatly où je suis resté ... et cela a aidé..merci une tonne ... Quoi qu'il en soit, je voudrais savoir la raison pour laquelle forEach boucle est incassable. Le cas échéant
Saurabh Tiwari

Cela ne devrait pas être la réponse acceptée car cela ne rompt pas la boucle forEach. C'est simplement un moyen de ne pas exécuter toute la logique à l'intérieur de la boucle.
Nebulosar

296

La angular.forEachboucle ne peut pas se rompre lors d'une correspondance de condition.

Mon conseil personnel est d'utiliser une boucle NATIVE FOR au lieu de angular.forEach.

La boucle NATIVE FOR est environ 90% plus rapide que les autres boucles for.

Pour la rupture de boucle, pour le résultat du test de boucle

UTILISER POUR boucle en ANGULAIRE:

var numbers = [0, 1, 2, 3, 4, 5];

for (var i = 0, len = numbers.length; i < len; i++) {
  if (numbers[i] === 1) {
    console.log('Loop is going to break.'); 
    break;
  }
  console.log('Loop will continue.');
}

1
Cela ne fonctionne pas pour moi. Il ne fait que terminer cette itération particulière de la boucle. Mais ensuite, il passe à l'itération suivante.
Ben

1
@Ben, Désolé ben, c'était mon erreur mais maintenant je mets à jour ma réponse après de longues recherches. J'espère que cela t'aidera . Merci
Nishchit Dhanani

1
@LGama: - Quel est votre cas ??
Nishchit Dhanani

3
jsperf.com/angular-foreach-performance testez-le sur votre propre navigateur pour décider quelle fonction vous devez choisir. J'ai testé sur IE11 et c'est aussi aussi rapide que dans la capture d'écran. A également testé Array.some () mais il est plus lent que Array.forEach () sur IE11 mais pourrait être plus rapide que angular.foreach ;-). Ou testez-le ici jsperf.com/angular-foreach-vs-native (tous les crédits vont à l'auteur original, pas à moi ;-))
Sebastian

6
Même avec jsperf, vous ne pouvez pas dire "natif pour environ 90% plus rapide". Dans votre scénario, cela dépend fortement du coût de l'exécution de la fonction interne et du nombre d'exécutions pouvant être enregistrées en quittant la boucle (pause) tôt.
hgoebl

22

veuillez utiliser certaines ou toutes les instances de ForEach,

Array.prototype.some:
some is much the same as forEach but it break when the callback returns true

Array.prototype.every:
every is almost identical to some except it's expecting false to break the loop.

Exemple pour certains:

var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];

ary.some(function (value, index, _ary) {
    console.log(index + ": " + value);
    return value === "JavaScript";
});

Exemple pour chaque:

var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];

ary.every(function(value, index, _ary) {
    console.log(index + ": " + value);
    return value.indexOf("Script") > -1;
});

Trouvez plus d'informations
http://www.jsnoob.com/2013/11/26/how-to-break-the-foreach/


no @ AngelS.Moreno, tout le monde préfère utiliser une variable locale au lieu d'une méthode conçue spécifiquement pour le cas en question
Oded Niv

18

Utilisez la méthode Array Some

 var exists = [0,1,2].some(function(count){
      return count == 1
 });

existe renverra true, et vous pouvez l'utiliser comme variable dans votre fonction

if(exists){
    console.log('this is true!')
}

Array Some Method - Javascript


4
Pour moi, la seule raison d'utiliser angular.forEach()est que je dois prendre en charge IE8, qui n'a pas Array.forEach()... ou Array.some().
Bennett McElwee

2
Vous pouvez polyfill Array.forEach facilement. Voir bas de page: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
zumalifeguard

6

Pour autant que je sache, Angular ne fournit pas une telle fonction. Vous pouvez utiliser des soulignementsfind() fonction pour cela (c'est essentiellement un forEach qui sort de la boucle une fois que la fonction retourne true).

http://underscorejs.org/#find


cela pourrait résoudre le problème latéralement, mais cela ne rompt pas en boucle la boucle.
Elise Chant

Ou natif pour la boucle
shanti

6

Si vous utilisez jQuery (donc pas jqLite) en conjonction avec AngularJS, vous pouvez itérer avec $ .each - qui permet de casser et de continuer en fonction de l'expression de la valeur de retour booléenne.

JSFiddle:

http://jsfiddle.net/JEcD2/1/

Javascript:

var array = ['foo', 'bar', 'yay'];
$.each(array, function(index, element){
    if (element === 'foo') {
        return true; // continue
    }
    console.log(this);
    if (element === 'bar') {
        return false; // break
    }
});

Remarque:

Bien que l'utilisation de jQuery ne soit pas mauvaise, les fonctions natives Array.some ou Array.every sont recommandées par MDN comme vous pouvez le lire dans la documentation native forEach :

"Il n'y a aucun moyen d'arrêter ou de rompre une boucle forEach. La solution consiste à utiliser Array.every ou Array.some"

Les exemples suivants sont fournis par MDN:

Array.some:

function isBigEnough(element, index, array){
    return (element >= 10);
}
var passed = [2, 5, 8, 1, 4].some(isBigEnough);
// passed is false
passed = [12, 5, 8, 1, 4].some(isBigEnough);
// passed is true

Array.every:

function isBigEnough(element, index, array){
    return (element >= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
// passed is false
passed = [12, 54, 18, 130, 44].every(isBigEnough);
// passed is true

6

Concrètement, vous pouvez sortir d'une forEachboucle, et de n'importe quel endroit, lever une exception.

try {
   angular.forEach([1,2,3], function(num) {
      if (num === 2) throw Error();
   });
} catch(e) {
    // anything
}

Cependant, il vaut mieux utiliser une autre bibliothèque ou implémenter votre propre fonction, un find fonction dans ce cas, donc votre code est le plus haut niveau.


10
Eh bien, vous avez répondu à la question! J'espère que personne ne le fera cependant :)
Jason Cox

Lancer une exception inutilement n'est pas un bon moyen de gérer la situation. Vérifiez plutôt la solution fournie par @ dnc253 stackoverflow.com/a/13844508/698127
Aamol

4

Essayez ceci comme pause;

angular.forEach([0,1,2], function(count){
  if(count == 1){
    return true;
  }
});

3

Comme les autres réponses l'indiquent, Angular ne fournit pas cette fonctionnalité. jQuery le fait cependant, et si vous avez chargé jQuery ainsi que Angular, vous pouvez utiliser

jQuery.each ( array, function ( index, value) {
    if(condition) return false; // this will cause a break in the iteration
})

Voir http://api.jquery.com/jquery.each/


2
Le PO a demandé une solution AngularJS, la bonne réponse est NON :)
Shannon Hochkins

3

Normalement, il n'y a aucun moyen de rompre une boucle "each" en javascript. Ce qui peut être fait habituellement est d'utiliser la méthode du "court-circuit".

    array.forEach(function(item) {
      // if the condition is not met, move on to the next round of iteration.
      if (!condition) return;

      // if the condition is met, do your logic here
      console.log('do stuff.')
    }


2

break n'est pas possible à réaliser en forEach angulaire, nous devons modifier forEach pour ce faire.

$scope.myuser = [{name: "Ravi"}, {name: "Bhushan"}, {name: "Thakur"}];  
                angular.forEach($scope.myuser, function(name){
                  if(name == "Bhushan") {
                    alert(name);
                    return forEach.break(); 
                    //break() is a function that returns an immutable object,e.g. an empty string
                  }
                });

Cette réponse ne semble pas complète. Veuillez indiquer si elle break()doit être définie ou si elle fait déjà partie de l'angulaire. Veuillez définir sinon.
géoidesic

2

Vous pouvez utiliser ceci:

var count = 0;
var arr = [0,1,2];
for(var i in arr){
   if(count == 1) break;
   //console.log(arr[i]);
}

1
var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];
var keepGoing = true;
ary.forEach(function(value, index, _ary) {
    console.log(index)
    keepGoing = true;
    ary.forEach(function(value, index, _ary) {
        if(keepGoing){ 
            if(index==2){
                keepGoing=false;
            }
            else{
                console.log(value)
            }

        }      
    });
});

0
$scope.arr = [0, 1, 2];  
$scope.dict = {}
for ( var i=0; i < $scope.arr.length; i++ ) {
    if ( $scope.arr[i] == 1 ) {
        $scope.exists = 'yes, 1 exists';
        break;
    }
 }
 if ( $scope.exists ) {
     angular.forEach ( $scope.arr, function ( value, index ) {
                      $scope.dict[index] = value;
     });
 }

0

Je préfère le faire par retour. Mettez la partie en boucle dans une fonction privée et revenez quand vous voulez rompre la boucle.


0

Je me rends compte que c'est vieux, mais un filtre matriciel peut faire ce dont vous avez besoin:

var arr = [0, 1, 2].filter(function (count) {
    return count < 1;
});

Vous pouvez ensuite exécuter arr.forEachet d'autres fonctions de tableau.

Je me rends compte que si vous avez l'intention de réduire complètement les opérations de boucle, cela ne fera probablement pas ce que vous voulez. Pour cela, vous l'utilisez au mieux while.


0

Cet exemple fonctionne. Essayez-le.

var array = [0,1,2];
for( var i = 0, ii = array.length; i < ii; i++){
  if(i === 1){
   break;
  }
}

1
Je suppose qu'il ne veut pas de forboucle, son cas d'utilisation a besoin d'un foreachpas forprobablement
Hassen Ch.

0

Utilisez Retour pour rompre la boucle.

angular.forEach([0,1,2], function(count){
  if(count == 1) {
    return;
  }
});

0
onSelectionChanged(event) {
    let selectdata = event['api']['immutableService']['gridOptionsWrapper']['gridOptions']['rowData'];
    let selected_flag = 0;

    selectdata.forEach(data => {
      if (data.selected == true) {
        selected_flag = 1;
      }
    });

    if (selected_flag == 1) {
      this.showForms = true;
    } else {
      this.showForms = false;
    }
}

-1

J'utiliserais returnau lieu de break.

angular.forEach([0,1,2], function(count){
  if(count == 1){
    return;
  }
});

Fonctionne comme un charme.


ce n'est pas une solution valable. look: function test () {angular.forEach ([1,2,3,4,5,6,7,8,9], function (value, index) {if (value == 2) return; console.log (valeur);})} sortie:> teste (); 1 3 4 5 6 7 8 9
otaviodecampos

-2

Ajoutez simplement $ index et procédez comme suit:

angular.forEach([0,1,2], function(count, $index) {
     if($index !== 1) {
          // do stuff
     }
}

OP veut sortir de la boucle.
Angel S. Moreno
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.