Angular JS break ForEach

256

Mam kątową pętlę foreach i chcę zerwać z pętli, jeśli dopasuję wartość. Poniższy kod nie działa.

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

Jak mogę to zdobyć?

Pulchny chłopiec
źródło
1
Nie rozumiem, dlaczego nie znajdziesz wartości zamiast przejść do pętli. Być może podany przez ciebie przykład nie opowiada całej historii, ale wolałbym zrobić to, co powiedział @Aman poniżej. Po co wchodzić w pętlę, jak wspomniano poniżej, i sprawdzać za każdym razem, gdy niektóre () robią to dokładnie w bardziej elegancki sposób. Pamiętaj, że jeśli traktujesz javascript jako język funkcjonalny, nie powinieneś używać go do struktur kontrolnych typu / while / break. Dlatego istnieją Foreach, Find, Some itp.
Adrian Rodriguez

Odpowiedzi:

264

Nie ma na to sposobu. Zobacz https://github.com/angular/angular.js/issues/263 . W zależności od tego, co robisz, możesz użyć wartości logicznej, aby po prostu nie wchodzić w ciało pętli. Coś jak:

var keepGoing = true;
angular.forEach([0,1,2], function(count){
  if(keepGoing) {
    if(count == 1){
      keepGoing = false;
    }
  }
});
dnc253
źródło
45
Wolę po prostu dodać !keepGoing && return;na górze funkcji, mniej kodu.
Andrew Joslin,
46
To nie jest najlepsza praktyka, tutaj kątowa dla każdej pętli nigdy się nie łamie, I nie ma nic do złamania kątowej. Dla każdego. Natywna dla pętli jest około 90% szybsza niż kątowa. Dla każdego. Dlatego lepiej jest użyć rodzimej pętli for, jeśli chcesz przerwać dopasowanie warunkowe. Dzięki
Nishchit Dhanani,
xcatly gdzie utknąłem ... a to pomogło .. dzięki tonie ... W każdym razie chciałbym poznać powód, dla którego pętla forEach jest niezniszczalna. Jeśli w ogóle
Saurabh Tiwari
To nie powinna być zaakceptowana odpowiedź, ponieważ nie przerywa pętli forEach. Jest to jedyny sposób, aby nie wykonywać całej logiki w pętli.
Nebulosar
296

angular.forEachPętla nie może złamać na stan meczu.

Moją osobistą radą jest użycie zamiast tego pętli NATIVE FORangular.forEach .

Pętla NATIVE FOR jest około 90% szybsza niż inne dla pętli.

Dla przerwania pętli, dla wyniku testu pętli

UŻYJ DO PĘTLI W KĄTU:

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
źródło
1
To mi nie działa. Wszystko, co robi, to zakończenie tej konkretnej iteracji pętli. Ale potem przechodzi do następnej iteracji.
Ben
1
@Ben, Przepraszamy Ben, To był mój błąd, ale teraz aktualizuję swoją odpowiedź po długich badaniach. Mam nadzieję, że to Ci pomoże . Dziękuję
Nishchit Dhanani,
1
@LGama: - Jaka jest Twoja sprawa?
Nishchit Dhanani
3
jsperf.com/angular-foreach-performance przetestuj go we własnej przeglądarce, aby zdecydować, którą funkcję wybrać. Testowałem na IE11 i jest on tak szybki, jak na zrzucie ekranu. Testowałem także Array.some (), ale jest wolniejszy niż Array.forEach () na IE11, ale może być szybszy niż angular.foreach ;-). Lub przetestuj tutaj jsperf.com/angular-foreach-vs-native (wszystkie napisy należą do oryginalnego autora, a nie do mnie ;-))
Sebastian,
6
Nawet z jsperf nie można powiedzieć, że „natywny dla jest około 90% szybszy”. W twoim scenariuszu zależy to bardzo od tego, jak drogie jest wykonanie funkcji wewnętrznej i ile wykonań można zapisać, wychodząc wcześniej z pętli (przerwania).
hgoebl
22

użyj niektórych lub wszystkich wystąpień 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.

Przykład dla niektórych:

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

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

Przykład dla każdego:

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

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

Znajdź więcej informacji
http://www.jsnoob.com/2013/11/26/how-to-break-the-foreach/

Neo Vijay
źródło
no @ AngelS.Moreno, wszyscy wolą używać zmiennej lokalnej zamiast metody zaprojektowanej specjalnie dla danego przypadku
Oded Niv
18

Użyj metody Array Some

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

istnieje, zwróci true, i możesz użyć tego jako zmiennej w swojej funkcji

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

Array Some Method - JavaScript

Aman Fahimullah
źródło
4
Dla mnie jedynym powodem do użycia angular.forEach()jest to, że muszę obsługiwać IE8, który nie ma Array.forEach()... lub Array.some().
Bennett McElwee
2
Możesz łatwo wypełnić polifill Array. ForEach. Zobacz dół strony: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
zumalifeguard
6

O ile mi wiadomo, Angular nie zapewnia takiej funkcji. Możesz do tego użyć find()funkcji podkreślenia (jest to w zasadzie forEach, który wyłamuje się z pętli, gdy funkcja zwróci wartość true).

http://underscorejs.org/#find

mna
źródło
może to rozwiązać problem bocznie, ale w rzeczywistości nie przerywa pętli.
Elise Chant,
Lub natywny dla pętli
shanti
6

Jeśli używasz jQuery (stąd nie jqLite) w połączeniu z AngularJS, możesz iterować z $ .each - co pozwala na łamanie i kontynuowanie w oparciu o wyrażenie logiczne.

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

Uwaga:

Chociaż za pomocą jQuery nie jest zła, zarówno rodzimych Array.some lub Array.every funkcje są zalecane przez MDN jak można przeczytać na rodzimym foreach dokumentacji:

„Nie ma możliwości zatrzymania lub przerwania pętli forEach. Rozwiązaniem jest użycie Array.every lub Array.some”

MDN zapewnia następujące przykłady:

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
źródło
6

Konkretnie, możesz wyjść z forEachpętli i z dowolnego miejsca, rzucić wyjątek.

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

Lepiej jest jednak użyć innej biblioteki lub zaimplementować własną funkcję, findw tym przypadku funkcję, więc kod ma najwyższy poziom.

Victor Aguilar
źródło
10
Odpowiedziałeś na pytanie! Mam nadzieję, że nikt tego nie zrobi :)
Jason Cox
Niepotrzebne zgłoszenie wyjątku nie jest dobrym sposobem radzenia sobie z sytuacją. Raczej sprawdź rozwiązanie dostarczone przez @ dnc253 stackoverflow.com/a/13844508/698127
Aamol
4

Spróbuj tego jako przerwy;

angular.forEach([0,1,2], function(count){
  if(count == 1){
    return true;
  }
});
panatoni
źródło
3

Jak podają inne odpowiedzi, Angular nie zapewnia tej funkcjonalności. jQuery działa jednak, a jeśli załadowałeś jQuery oraz Angular, możesz użyć

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

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

Nik Dow
źródło
2
OP poprosił o rozwiązanie AngularJS, prawidłowa odpowiedź brzmi NIE :)
Shannon Hochkins
3

Zwykle nie ma sposobu na przerwanie pętli „each” w javascript. Co zwykle można zrobić, to zastosować metodę „zwarcia”.

    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
źródło
2

break nie jest możliwe do osiągnięcia w forEach kątowym, musimy zmodyfikować forEach, aby to zrobić.

$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
źródło
Ta odpowiedź nie wydaje się pełna. Proszę wskazać, czy break()należy zdefiniować, czy jest to już część kąta. Proszę określić, jeśli nie.
geoidesic
2

Możesz użyć tego:

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

        }      
    });
});
użytkownik1693371
źródło
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 ...
źródło
0

Wolałbym to zrobić w drodze powrotnej. Umieść część zapętloną w funkcji prywatnej i wróć, gdy chcesz przerwać pętlę.

PrabaharanKathiresan
źródło
0

Wiem, że to stare, ale filtr tablicowy może zrobić to, czego potrzebujesz:

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

Następnie można uruchomić arr.forEachi inne funkcje tablicowe.

Zdaję sobie sprawę, że jeśli zamierzasz całkowicie ograniczyć operacje na pętli, prawdopodobnie nie zrobi to, co chcesz. Do tego najlepiej wykorzystać while.

Linia brzegowa
źródło
0

Ten przykład działa. Spróbuj.

var array = [0,1,2];
for( var i = 0, ii = array.length; i < ii; i++){
  if(i === 1){
   break;
  }
}
Maikel Rosabal
źródło
1
Wydaje mi się, że nie chce forpętli, jego przypadek użycia foreachnie wymaga forchyba
Hassen Ch.
0

Użyj Return, aby przerwać pętlę.

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

Użyłbym returnzamiast break.

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

Działa jak marzenie.

Aakash
źródło
to nie jest poprawne rozwiązanie. look: funkcja test () {angular.forEach ([1,2,3,4,5,6,7,8,9], funkcja (wartość, indeks) {if (wartość == 2) return; console.log (wartość);})} wyjście:> teste (); 1 3 4 5 6 7 8 9
otaviodecampos 13.03.19
-2

Po prostu dodaj $ index i wykonaj następujące czynności:

angular.forEach([0,1,2], function(count, $index) {
     if($index !== 1) {
          // do stuff
     }
}
Sułtan
źródło
OP chce wyjść z pętli.
Angel S. Moreno