JS angular quebra ForEach

256

Eu tenho um loop foreach angular e quero interromper o loop se eu corresponder a um valor. O código a seguir não funciona.

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

Como posso conseguir isso?

Menino gordinho
fonte
1
Não entendo por que você não encontra apenas o valor em vez de entrar em loop. Talvez o exemplo que você deu não esteja contando toda a história, mas prefiro fazer o que @Aman disse abaixo. Por que entrar no loop como mencionado abaixo e executar uma verificação sempre que some () faz exatamente isso de uma maneira mais elegante. Lembre-se de que se você tratar o javascript como uma linguagem funcional, não haverá sentido em usá-las para estruturas de controle do tipo / while / break. É por isso que foreach, encontrar, alguns, etc existem
Adrian Rodriguez

Respostas:

264

Não há como fazer isso. Consulte https://github.com/angular/angular.js/issues/263 . Dependendo do que você está fazendo, você pode usar um booleano para não entrar no corpo do loop. Algo como:

var keepGoing = true;
angular.forEach([0,1,2], function(count){
  if(keepGoing) {
    if(count == 1){
      keepGoing = false;
    }
  }
});
dnc253
fonte
45
Prefiro adicionar um !keepGoing && return;ao topo da função, menos código.
Andrew Joslin
46
Isso não é uma prática recomendada, aqui o loop forEach angular nunca é interrompido E não há nada para quebrar o angular.forEach. O loop for nativo é cerca de 90% mais rápido que o angular. Portanto, é melhor usar o loop for nativo quando você deseja interromper a correspondência de condições. Obrigado
Nishchit Dhanani
xcatly onde eu fiquei ... e isso ajudou .. muito obrigado ... De qualquer forma, eu gostaria de saber o motivo de tornar cada loop inquebrável. Se houver #
Saurabh Tiwari
Essa não deve ser a resposta aceita, pois não interrompe o loop forEach. É apenas uma maneira de não executar toda a lógica dentro do loop.
Nebulosar
296

O angular.forEachloop não pode quebrar em uma correspondência de condição.

Meu conselho pessoal é usar um loop NATIVE FOR em vez de angular.forEach.

O loop NATIVE FOR é cerca de 90% mais rápido que o outro para loops.

Para quebra de loop, para resultado de teste de loop

USE FOR loop em angular:

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
fonte
1
Isso não funciona para mim. Tudo o que faz é concluir essa iteração específica do loop. Mas então ele passa para a próxima iteração.
Ben
1
@ Ben, desculpe ben, foi meu erro, mas agora eu atualizo minha resposta após uma longa pesquisa. Eu espero que isso te ajude . Obrigado
Nishchit Dhanani
1
@ Gamma: - Qual é o seu caso?
Nishchit Dhanani
3
jsperf.com/angular-foreach-performance teste-o em seu próprio navegador para decidir qual função você deve escolher. Eu testei no IE11 e também é tão rápido quanto na captura de tela. Também testou Array.some (), mas é mais lento que Array.forEach () no IE11, mas pode ser mais rápido que angular.foreach ;-). Ou testá-lo aqui jsperf.com/angular-foreach-vs-native (todos os créditos vão para o autor original, não me ;-))
Sebastian
6
Mesmo com o jsperf, você não pode dizer "nativo para é cerca de 90% mais rápido". No seu cenário, isso depende muito de quão cara é a execução da função interna e de quantas execuções podem ser salvas saindo do loop (break) mais cedo.
hgoebl
22

use algumas ou todas as instâncias do 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.

Exemplo para alguns:

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

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

Exemplo para cada:

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

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

Encontre mais informações
http://www.jsnoob.com/2013/11/26/how-to-break-the-foreach/

Neo Vijay
fonte
não @ AngelS.Moreno, todos preferem usar uma variável local em vez de um método desenvolvido especificamente para o caso em questão
Oded Niv
18

Use o método Array Some

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

existe retornará verdadeiro e você pode usá-lo como uma variável em sua função

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

Array Some Method - Javascript

Aman Fahimullah
fonte
4
Para mim, a única razão para usar angular.forEach()é que eu tenho que dar suporte ao IE8, que não tem Array.forEach()... ou Array.some().
Bennett McElwee 26/03
2
Você pode polyfill Array.forEach facilmente. Veja o final da página: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
zumalifeguard
6

Até onde eu sei, o Angular não fornece essa função. Você pode usar a find()função de sublinhado para isso (é basicamente um forEach que interrompe o loop quando a função retorna verdadeira).

http://underscorejs.org/#find

mna
fonte
isso pode resolver o problema lateralmente, mas, de fato, não quebra o loop.
Elise Chant
Ou nativo para loop
shanti
6

Se você usar o jQuery (portanto, não o jqLite) em conjunto com o AngularJS, poderá iterar com $ .each - o que permite interromper e continuar com base na expressão do valor de retorno booleano.

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
    }
});

Nota:

Embora o uso do jQuery não seja ruim, as funções nativas Array.some ou Array.every são recomendadas pelo MDN, pois você pode ler na documentação nativa do forEach :

"Não há como parar ou interromper um loop forEach. A solução é usar Array.every ou Array.some"

Os exemplos a seguir são fornecidos pelo 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
fonte
6

Concretamente, você pode sair de um forEachloop e de qualquer lugar, lançar uma exceção.

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

No entanto, é melhor se você usar outra biblioteca ou implementar sua própria função, uma findfunção nesse caso, para que seu código seja de alto nível.

Victor Aguilar
fonte
10
Bem, você respondeu à pergunta! Espero que ninguém faz isso embora :)
Jason Cox
Lançar uma exceção desnecessariamente não é uma boa maneira de lidar com a situação. Verifique antes, a solução fornecida pela @ dnc253 stackoverflow.com/a/13844508/698127
Aamol
4

Tente isso como pausa;

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

Como as outras respostas afirmam, o Angular não fornece essa funcionalidade. No entanto, o jQuery faz isso e, se você carregou o jQuery e o Angular, pode usar

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

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

Nik Dow
fonte
2
O OP pediu uma solução AngularJS, a resposta correta é NO :)
Shannon Hochkins
3

Normalmente, não há como quebrar um loop "each" em javascript. O que geralmente pode ser feito é usar o método de "curto-circuito".

    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
fonte
2

break não é possível obter no forEach angular, precisamos modificar o forEach para fazer isso.

$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
fonte
Esta resposta não parece completa. Indique se break()precisa ser definido ou se já faz parte do angular. Por favor, defina se não.
geoidesic 29/09/16
2

Você pode usar isto:

var count = 0;
var arr = [0,1,2];
for(var i in arr){
   if(count == 1) break;
   //console.log(arr[i]);
}
endrcn
fonte
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
fonte
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 ...
fonte
0

Eu preferiria fazer isso de volta. Coloque a parte de loop na função privada e retorne quando desejar interromper o loop.

PrabaharanKathiresan
fonte
0

Sei que isso é antigo, mas um filtro de matriz pode fazer o que você precisa:

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

Você pode executar arr.forEache outras funções da matriz.

Sei que, se você pretende reduzir completamente as operações de loop, isso provavelmente não fará o que você deseja. Para isso você melhor usa while.

Shoreline
fonte
0

Este exemplo funciona. Tente.

var array = [0,1,2];
for( var i = 0, ii = array.length; i < ii; i++){
  if(i === 1){
   break;
  }
}
Maikel Rosabal
fonte
1
Eu acho que ele não quer um forloop, seu caso de uso foreachnão precisa de um forprovavelmente
Hassen Ch.
0

Use Return para interromper o loop.

angular.forEach([0,1,2], function(count){
  if(count == 1) {
    return;
  }
});
Shanmugarajan
fonte
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
fonte
-1

Eu usaria em returnvez de break.

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

Funciona como um encanto.

Aakash
fonte
Esta não é uma solução válida. look: function test () {angular.forEach ([1,2,3,4,5,6,7,8,9], função (valor, índice) {if (value == 2) return; console.log (valor);})} saída:> teste (); 1 3 4 5 6 7 8 9
otaviodecampos 13/03/19
-2

Apenas adicione $ index e faça o seguinte:

angular.forEach([0,1,2], function(count, $index) {
     if($index !== 1) {
          // do stuff
     }
}
Sultão
fonte
O OP quer sair do circuito.
Angel S. Moreno