93

I have a the below code, on which i am unable to break the loop on certain conditions.

function isVoteTally(): boolean {
  let count = false;
  this.tab.committee.ratings.forEach((element) => {
    const _fo = this.isEmptyOrNull(element.ratings.finalOutcome.finaloutlook);
    const _foreign = this.isEmptyOrNull(element.ratings.finalOutcome.foreign);
    const _local = this.isEmptyOrNull(element.ratings.finalOutcome.local);
    const _tally =
      element.ratings.finalOutcome.voteTally.maj +
      element.ratings.finalOutcome.voteTally.dis;

    if (_fo == false && _foreign == false && _local == false) {
      if (_tally > 0) {
        return (count = false); // ⭐
      }
    } else {
      if (_tally < 0) {
        return (count = false); // ⭐
      }
    }
  });
  return count;
}

On the star-marked areas, I want to break the code and return the boolean value, but I am unable to do. How can it be done?

starball
  • 20,030
  • 7
  • 43
  • 238
Arka
  • 985
  • 1
  • 8
  • 15
  • 4
    The MDN is a great resource on JavaScript and the types/methods available. Here's the page on [Array.ForEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach). And it has a section specifically about alternatives you can use if you need to break. "Early termination may be accomplished with:" –  Aug 08 '18 at 13:20
  • Please update the best answer to that provided by @Roberc – Kunal Sep 01 '20 at 19:51
  • Does this answer your question? [Short circuit Array.forEach like calling break](https://stackoverflow.com/questions/2641347/short-circuit-array-foreach-like-calling-break) – Liam Jun 11 '21 at 10:49
  • Also the question should be renamed to: How to break ForEach Loop by returning a value in TypeScript. At the moment the title is a little bit misleading because you can break forEach loop by returning nothing. – C0mpl3x Jun 17 '21 at 12:58
  • The comment from @user310988 has been the best answer I've seen throughout dozens of minutes of searching. Roberc's answer only solves for one case so that should not be the accepted answer. In an ocean of incorrect/incomplete answers, I finally find the proper one. – Wolf Nov 30 '22 at 11:11
  • This is crying for a [mre]. I'm not editing to turn it into one because I'm not sure if it's in my place to do so. – starball Dec 21 '22 at 20:46

7 Answers7

150

this.tab.committee.ratings.forEach is not an operator.

Typescript allows for much more readable code.

Use a for loop in style as follows:

for (let a of this.tab.committee.ratings) {
   if (something_wrong) break;
}

p.s. forget "coding as with jQuery" in Angular. It just doesn't work.

WoJ
  • 27,165
  • 48
  • 180
  • 345
Roberc
  • 1,816
  • 3
  • 9
  • 12
  • I am not able to find documentation for `of`. – Mangesh May 20 '20 at 13:22
  • @Mangesh this syntax is not Angular-specific. It's new ECMAScript standard. You can read about it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of – Roberc May 21 '20 at 14:36
  • 3
    For large arrays, this is more performant since it breaks upon first match, and does not need to go through every element. – hkong Jun 27 '20 at 16:14
  • @Mangesh: https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html#forof-vs-forin-statements – Kunal Sep 01 '20 at 19:52
  • 1
    Nice! Better that `.forEach` for my taste. Even if that's not directly answering question. – Camille Feb 05 '21 at 11:53
  • 3
    Just to add, always prefer using `const` over `let`. You won't want to attribute a new value to `a` here. – Guilherme Taffarel Bergamin Feb 04 '22 at 13:41
52

It is not possible to break from forEach() normally.

Alternatively you can use Array.every() because you wish to return false while breaking the loop.

If you want to return true, then you can use Array.some()

this.tab.committee.ratings.every(element => {

  const _fo = this.isEmptyOrNull(element.ratings.finalOutcome.finaloutlook);
  const _foreign = this.isEmptyOrNull(element.ratings.finalOutcome.foreign);
  const _local = this.isEmptyOrNull(element.ratings.finalOutcome.local);
  const _tally = element.ratings.finalOutcome.voteTally.maj + element.ratings.finalOutcome.voteTally.dis;

  if (_fo == false && _foreign == false && _local == false) {
    if (_tally > 0) {
      **return count = false;**
    }
  } else {
    if (_tally < 0) {
      **return count = false;**
    }
  }
});
Amit Chigadani
  • 28,482
  • 13
  • 80
  • 98
9

You cannot ‘break’, it won’t even run because the break instruction is not technically in a loop. Solution? Just use a normal for loop. Nobody would laugh at you.

Skraloupak
  • 374
  • 4
  • 5
2

I think even better solution is to use for. With for you can return a value when it's found and break the loop. It's a lot cleaner solution

for (element of this.tab.committee.ratings) {
// and here you use your element, when you return a values it stops the cycle

if (element === something){
 return element;
 }
}
C0mpl3x
  • 480
  • 4
  • 21
-2

const blocks = document.querySelectorAll('.block');
var breakMe = false;

blocks.forEach((block, i) => {
    if(breakMe == false) {
        /*code that you want*/ 
        if(i < 2) {
            block.style.background = 'red';
        } else if(i != 4) {
            block.style.background = 'blue';
        } else if(i == 4) {
            breakMe = true;
            /*change breackMe to true if you want to breack forEach*/
        }
    }

})
<!DOCTYPE html>
  <html lang="en">
  <body>
    <div id="container">
      <div class="block" style="width: 200px; height: 200px; background: purple; margin: 50px"></div>      
      <div class="block" style="width: 200px; height: 200px; background: purple; margin: 50px"></div>
      <div class="block" style="width: 200px; height: 200px; background: purple; margin: 50px"></div>
      <div class="block" style="width: 200px; height: 200px; background: purple; margin: 50px"></div>
      <div class="block" style="width: 200px; height: 200px; background: purple; margin: 50px"></div>
    </div>
  </body>
  </html>
-3

You can break foreach loop by using try-catch statement

try {
  arr.forEach((item:any) => {
    if(item === '2') {
      throw "break";
    }
    console.log('Item ID: ', item);
  });  
} catch(e) {
  console.log('Warn Error',e);
}
  • 1
    Don't use exceptions to brake loop, too expensive and purpose of exceptions is not that. Just use a regular for... loop, or arr.find() per example. – Nikola Svitlica May 29 '23 at 08:04
-21

simply do return false;. It will break.

Riddhi
  • 201
  • 1
  • 10
  • 13
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach "There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool." –  Aug 08 '18 at 13:17