Кутовий JS розрив ForEach


256

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

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

Як я можу це отримати?


1
Я не розумію, чому ви не просто знайдете значення замість того, щоб піти в цикл. Можливо, приклад, який ви навели, не розповідає всієї історії, але я б краще зробив те, що @Aman сказав нижче. Навіщо йти в цикл, як зазначено нижче, і запускати перевірку кожен раз, коли деякі () роблять саме це в більш елегантному стилі. Пам’ятайте, що якщо ви розглядаєте javascript як функціональну мову, не повинно бути сенсу використовувати ці для керуючих структур / while / break. Ось чому пропонують, знаходять, деякі тощо існують
— Адріан Родрігес

Відповіді:


264

Немає цього зробити. Дивіться https://github.com/angular/angular.js/isissue/263 . Залежно від того, що ви робите, ви можете використовувати булеву форму, щоб просто не потрапляти в тіло петлі. Щось на зразок:

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

45
Я вважаю за краще просто додати !keepGoing && return;верхню частину функції, менше коду.
— Ендрю Джослін

46
Це не найкращі практики, тут кутовий цикл для кожного не порушується, і кут неможливо зламати. Рідний для циклу приблизно на 90% швидший, ніж кутовий. Для кожного. Тож краще використовувати нативні для циклу, коли ви хочете перервати умовні збіги. Спасибі
— Nishchit Dhanani

xcatly там, де я застряг ... і це допомогло ... дякую за тонну ... У будь-якому разі, я хотів би знати причину того, щоб зробити для кожного циклу нерозривний. Якщо є
— Саурабх Тіварі

Це не повинно бути прийнятою відповіддю, оскільки це не порушує цикл forEach. Це дійсно спосіб не виконувати всю логіку всередині циклу.
— Небулосар

296

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

Моя особиста порада замість цього використовувати цикл NATIVE FORangular.forEach .

Цикл NATIVE FOR на 90% швидший, ніж інший для циклів.

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

ВИКОРИСТАННЯ ДЛЯ ШЛЯХУ В АНГУЛЬНОМУ:

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
@Ben, Вибачте, бен, це була моя помилка, але тепер я оновлюю свою відповідь після тривалих досліджень. Я сподіваюся, що це вам допоможе. Дякую
— 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 ви не можете сказати, що "рідне для" на 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

Використовуйте метод масиву

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

існує, повернеться true, і ви можете використовувати це як змінну у своїй функції

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

Масив деякий метод - Javascript


4
Для мене єдиною причиною використання angular.forEach()є те, що я повинен підтримувати IE8, у якого немає Array.forEach()... або Array.some().
— Bennett McElwee

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

6

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

http://underscorejs.org/#find


це може вирішити проблему збоку, але це не перерве цикл.
— Elise Chant

Або рідний для циклу
— шанті

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 не є поганим, обидві функції Array.some або Array.every рекомендуються MDN, як ви можете прочитати в натурній документації 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 Неможливо досягти в кутовому дляEach, нам потрібно модифікувати 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певно
— Хассен Ч.


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

Працює як шарм.


це неправильне рішення. дивіться: тест функції () {angular.forEach ([1,2,3,4,5,6,7,8,9], функція (значення, індекс) {if (значення == 2) return; console.log (значення);})} вихід:> teste (); 1 3 4 5 6 7 8 9
— отавіодекампос

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.