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ć?


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

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

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/


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


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


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

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.


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

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/


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.')
    }


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

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

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

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


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.


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

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

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

Użyłbym returnzamiast break.

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

Działa jak marzenie.


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

OP chce wyjść z pętli.
Angel S. Moreno
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.