Угловой JS break ForEach


256

У меня есть угловой цикл foreach, и я хочу выйти из цикла, если я сопоставлю значение. Следующий код не работает.

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

Как я могу получить это?


1
Я не понимаю, почему вы не просто находите значение, а не зацикливаетесь. Возможно, приведенный вами пример не рассказывает всей истории, но я бы лучше сделал то, что сказал @Aman ниже. Зачем входить в цикл, как указано ниже, и запускать проверку каждый раз, когда some () делает это более элегантным способом. Помните, что если вы рассматриваете javascript как функциональный язык, не должно быть смысла использовать их для структур управления типа / while / break. Вот почему существуют foreach, find, some и т. Д.
Adrian Rodriguez,

Ответы:


264

Там нет никакого способа сделать это. См. Https://github.com/angular/angular.js/issues/263 . В зависимости от того, что вы делаете, вы можете использовать логическое значение, чтобы просто не входить в тело цикла. Что-то вроде:

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

45
Я бы предпочел просто добавить !keepGoing && return;в начало функции меньше кода.
Эндрю Джослин

46
Это не лучшая практика, здесь угловой цикл forEach никогда не прерывается, и нет ничего, что могло бы нарушить angular.forEach. Собственный цикл for примерно на 90% быстрее, чем angular.forEach. Поэтому лучше использовать native for loop, если вы хотите прервать соответствие условия. Спасибо
Nishchit Dhanani

xcatly, где я застрял ... и это помогло ... спасибо за тонну ... В любом случае, я хотел бы знать причину, по которой цикл forEach нерушим. Если есть
Саураб Тивари

Это не должен быть принятый ответ, поскольку он не нарушает цикл forEach. Это просто способ не выполнять всю логику внутри цикла.
Небулосар

296

angular.forEachЦикл не может сломаться на матче состояния.

Мой личный совет - использовать цикл NATIVE FOR вместо angular.forEach.

Цикл NATIVE FOR работает примерно на 90% быстрее, чем цикл for other.

Для разрыва цикла, для результата проверки цикла

ИСПОЛЬЗОВАТЬ ДЛЯ ЦИКЛА В УГЛОВОЙ:

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
Это не работает для меня. Все, что он делает, это заканчивает эту конкретную итерацию цикла. Но затем он переходит к следующей итерации.
Бен

1
@ Бен, прости Бен, это была моя ошибка, но теперь я обновляю свой ответ после долгих исследований. Я надеюсь, что это поможет вам . Спасибо
Nishchit Dhanani

1
@LGama: - Каков твой случай?
Nishchit Dhanani

3
jsperf.com/angular-foreach-performance протестируйте его в своем браузере, чтобы решить, какую функцию выбрать. Я проверил на IE11, и это также быстро, как на скриншоте. Также протестировал Array.some (), но он медленнее, чем Array.forEach () в IE11, но может быть быстрее, чем angular.foreach ;-). Или проверьте это здесь jsperf.com/angular-foreach-vs-native (все работы принадлежат оригинальному автору, а не мне ;-))
Себастьян

6
Даже с jsperf вы не можете сказать, что "native for примерно на 90% быстрее". В вашем сценарии это сильно зависит от того, насколько дорогое выполнение внутренней функции и сколько выполнений может быть сохранено путем раннего выхода из цикла (прерывания).
hgoebl

22

пожалуйста, используйте некоторые или все экземпляры 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.

Пример для некоторых:

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

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

Пример для каждого:

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

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

Найти дополнительную информацию
http://www.jsnoob.com/2013/11/26/how-to-break-the-foreach/


нет @ AngelS.Moreno, все предпочитают использовать локальную переменную вместо метода, разработанного специально для данного случая
Одед Нив

18

Используйте метод Array Some

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

существующие вернут true, и вы можете использовать это как переменную в своей функции

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

Array Some Method - Javascript


4
Для меня единственная причина использования angular.forEach()заключается в том, что я должен поддерживать IE8, который не имеет Array.forEach()... или Array.some().
Беннет МакЭлви,

2
Вы можете легко заполнить Array.forEach. См. Внизу страницы: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
zumalifeguard

6

Насколько я знаю, Angular не предоставляет такой функции. Вы можете использовать find()функцию подчеркивания для этого (это в основном forEach, который выходит из цикла, когда функция возвращает true).

http://underscorejs.org/#find


это может решить проблему в боковом направлении, но на самом деле это не нарушает петлю.
Elise Chant

Или родной цикл
Shanti

6

Если вы используете jQuery (следовательно, не jqLite) в сочетании с AngularJS, вы можете выполнять итерации с $ .each - что позволяет ломать и продолжать на основе выражения логического возвращаемого значения.

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

Примечание:

Хотя использование jQuery неплохо, MDN рекомендует использовать как нативные функции Array.some, так и Array.every , поскольку вы можете прочитать в нативной документации forEach :

«Невозможно остановить или прервать цикл forEach. Решение - использовать Array.every или Array.some»

Следующие примеры предоставлены 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

Конкретно, вы можете выйти из forEachцикла и в любом месте выдать исключение.

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

Однако лучше, если вы используете другую библиотеку или реализуете свою собственную функцию, findв данном случае функцию, поэтому ваш код является наиболее высокоуровневым.


10
Ну, вы ответили на вопрос! Я надеюсь, что никто не делает этого, хотя :)
Джейсон Кокс

Бросать исключение излишне - не лучший способ справиться с ситуацией. Скорее проверьте решение, предоставленное @ dnc253 stackoverflow.com/a/13844508/698127
Aamol

4

Попробуйте это как перерыв;

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

3

Как говорится в других ответах, Angular не предоставляет эту функциональность. Однако jQuery делает, и если вы загрузили jQuery так же, как Angular, вы можете использовать

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

Смотрите http://api.jquery.com/jquery.each/


2
ОП попросил решение AngularJS, правильный ответ - НЕТ :)
Шеннон Хохкинс

3

Обычно в javascript нет способа разорвать цикл «каждый». Обычно можно использовать метод «короткого замыкания».

    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 в angular forEach невозможно добиться успеха, для этого нужно изменить forEach.

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

Этот ответ не кажется полным. Пожалуйста, укажите, break()должно ли быть определено или не является ли это уже угловой частью. Пожалуйста, определите, если нет.
геоидезическая

2

Вы можете использовать это:

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

Я бы предпочел сделать это по возвращении. Поместите часть цикла в приватную функцию и возвращайте ее, когда хотите разорвать цикл.


0

Я понимаю, что это старый, но фильтр массива может делать то, что вам нужно:

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

Затем вы можете запустить arr.forEachи другие функции массива.

Я понимаю, что если вы намерены полностью сократить циклические операции, это, вероятно, не будет делать то, что вы хотите. Для этого вам лучше всего использовать while.


0

Этот пример работает. Попытайся.

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

1
Я предполагаю, что он не хочет forпетли, его сценарий foreachиспользования, forвероятно, не нужен
Hassen Ch.


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

Я бы использовал returnвместо break.

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

Работает как шарм.


это не правильное решение. look: function test () {angular.forEach ([1,2,3,4,5,6,7,8,9], function (value, index) {if (value == 2) return; console.log (значение);})} output:> teste (); 1 3 4 5 6 7 8 9
otaviodecampos

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.