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?

Garçon grassouillet
la source
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;
    }
  }
});
dnc253
la source
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.');
}
Nishchit Dhanani
la source
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/

Neo Vijay
la source
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

Aman Fahimullah
la source
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

mna
la source
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
conceptdeluxe
la source
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.

Victor Aguilar
la source
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;
  }
});
panatoni
la source
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/

Nik Dow
la source
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.')
    }

Downhillski
la source
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
                  }
                });
rb4bhushan
la source
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]);
}
endrcn
la source
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)
            }

        }      
    });
});
user1693371
la source
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;
     });
 }
solanki ...
la source
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.

PrabaharanKathiresan
la source
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.

Littoral
la source
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;
  }
}
Maikel Rosabal
la source
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;
  }
});
Shanmugarajan
la source
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;
    }
}
poovarasi sekar
la source
-1

J'utiliserais returnau lieu de break.

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

Fonctionne comme un charme.

Aakash
la source
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
     }
}
Sultan
la source
OP veut sortir de la boucle.
Angel S. Moreno