The array forEach() method is commonly used among TypeScript and JavaScript developers. However, developers often come across unexpected behaviors trying to exit or break the forEach() method using the break keyword to prevent executing any additional logic to subsequent elements of an array.

For instance, if we try to run the following example:

const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const maxValue = 4;

myArray.forEach((value) => {
   if (value > maxValue) break;

   console.log('Current value is ', value);
});

Unfortunately, this will cause errors in your code.

If you are using TypeScript, it will throw the following error: Jump target cannot cross function boundary.(1107)

Error: Jump target cannot cross function boundary.(1107)

If you are using JavaScript, it will throw the following error: Uncaught SyntaxError: Illegal break statement

Error: Uncaught SyntaxError: Illegal break statement

Fortunately, there are different ways to fix this issue.

Throw an error to break the loop

To fix this error and successfully break the forEach() loop either in TypeScript or JavaScript, wrap the forEach() logic inside a try/catch statement and throw an error inside the forEach() callback function to break the loop.

Throwing an error forces the program to immediately stop running any additional logic. Hence, “breaking” the loop.

const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const maxValue = 4;

try {
   myArray.forEach((value) => {
      if (value > maxValue) throw new Error("Max limit reached");

      console.log('Current value is ', value);
   });
} catch(error) {
   console.error("error ", error);
}

While this solution works, it opens the room to let the code keep running in case there is an unexpected error different from our custom Error("Max limit reached") error.

To make sure we keep running the code as long as we trigger are custom error, verify the error contains the message property. Also, verify the error.message value matches the custom message. This can look like the following example:

const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const maxValue = 4;
const errorMaxLimit = "Max limit reached";

try {
   myArray.forEach((value) => {
      if (value > maxValue) throw new Error(errorMaxLimit);

      console.log('Current value is ', value);
   });
} catch(error) {
   if (!error.property || error.property !== errorMaxLimit) {
     // another error has happened 
     throw error;
   }
}

Use return to prevent running undesired logic (alternative solution)

Another solution is to use the return keyword instead of the break keyword to prevent running undesired logic.

const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const maxValue = 4;

myArray.forEach((value) => {
   if (value > maxValue) return; // use the "return" keyword instead of the "break" keyword

   console.log('Current value is ', value);
});

For instance, the previous snippet of code will no longer log “Current value is ” for each of the elements of the array myArray. While using the return keyword will prevent running undesired logic, this solution can suffer from performance issues.

Why using return inside the forEach() loop causes performance issues?

If you think about it, using the return keyword doesn’t actually “break” the forEach() loop. It only prevents running undesired logic.

Hence, if myArray array has, .i.e., 100000 elements, the callback function will execute for each of the array elements even if it only logs “Current value is ” for the first four elements.

Therefore, we are still running unnecessary logic in the background.

Why do you recommend using return if it can have performance issues?

It all comes down to how having an idea of the average number of elements in your array.

For instance, if I know my array will typically have a few more elements than the limit established prior to deciding to programmatically break the loop, I would rather use the return keyword than throwing an error and wrapping the forEach() loop in a try/catch statement.

In other words, it is cleaner and I consider “ok” to compromise performance and executing a few additional callback executions for the sake of preventing adding custom logic to break the forEach() loop.

Any time more logic is added to the code it means additional testing needs to be done upon the new logic.

On the other hand, if the loop might have a big gap between the limit established to break the loop and the number of elements the array could actually have, I would not use the return keyword as my first solution.

Use a traditional for loop or a for of loop and preserve the break keyword

Another solution is to not use the forEach() loop and use a traditional for loop. In that way, there wouldn’t be the need to throw an error as the break keyword would effectively break the loop.

const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const maxValue = 4;

for (let i = 0; i < myArray.length; i++) {
   const value = myArray[i];    
    
   if (value > maxValue) break;

   console.log('Current value is ', value);
}

This solution also applies when using a for of loop.

const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const maxValue = 4;

for (let value of myArray) {
    const value = myArray[i];    
    
   if (value > maxValue) break;

   console.log('Current value is ', value);
}

While this might not be necessarily a solution to breaking the forEach() loop, using the for or for of loop along with the break keyword would be a much simpler approach to solving the main issue which is to break the loop.

Conclusion

It is easy to fool yourself by thinking the break keyword will break the loop when using the forEach() method. Luckily, there are different alternatives available to break the loop or prevent from running undesired logic by making little tweaks to our code.

Did this article solve your problem?

Hopefully, this article provides you with different solutions you can apply to a common error that most likely any TypeScript/JavaScript developer has experienced at least once in their career.

Share your thoughts by replying on Twitter of Become A Better Programmer or to my personal Twitter account.

Author