Угловой 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;
    }
  }
});
dnc253
источник
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
conceptdeluxe
источник
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;
  }
});
panatoni
источник
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.')
    }

Downhillski
источник
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
                  }
                });
rb4bhushan
источник
Этот ответ не кажется полным. Пожалуйста, укажите, break()должно ли быть определено или не является ли это уже угловой частью. Пожалуйста, определите, если нет.
геоидезическая
2

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

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

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

PrabaharanKathiresan
источник
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

Используйте Return, чтобы разорвать петлю.

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;
    }
}
Poovarasi Sekar
источник
-1

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

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

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

Aakash
источник
это не правильное решение. 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
-2

Просто добавьте $ index и сделайте следующее:

angular.forEach([0,1,2], function(count, $index) {
     if($index !== 1) {
          // do stuff
     }
}
султан
источник
ОП хочет вырваться из цикла.
Ангел С. Морено