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)
If you are using JavaScript, it will throw the following error: Uncaught SyntaxError: Illegal break statement
Fortunately, there are different ways to fix this issue.
Table of Contents
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.