1

Why can't I break out of a reduce in Javascript?

Seems a simple return or even a throw will not break it at all. Exactly why does it need to loop through all of the values?

coolpasta
  • 725
  • 5
  • 19
  • You can refer this https://stackoverflow.com/questions/36144406/how-to-break-on-reduce-method – ganesh phirke Jun 25 '19 at 05:41
  • 2
    Why do you want to break out of reduce for? – zer00ne Jun 25 '19 at 05:41
  • @AngelosChalaris It's not. I asked what about its design made the original implementers say "you will always go through each item"? That question treats the act of breaking a `reduce` and how to. I'm interested on the "why can't I". – coolpasta Jun 25 '19 at 06:07
  • 1
    @coolpasta why *wouldn't* it go through each item? All of the iteration methods never break - `map`, `forEach`, `filter`, etc. It absolutely makes sense because you'd use them when you don't want to stop the iteration. So, your question is backwards. – VLAZ Jun 25 '19 at 06:09

2 Answers2

6

Because that's what it's designed to do - it will always loop through all items in the array, just like most other array methods like forEach and map.

If, past some point, you want to effectively ignore what comes afterwards, just return the current accumulator, for example:

const partialSum = [1, 2, 3, 4].reduce((a, num) => {
  if (a > 3) {
    return a;
  }
  return a + num;
}, 0);

console.log(partialSum);

If you want to find an element in the array instead, you should use .find, which will terminate the loop as soon as a match is found:

const arr = [
  { prop: 'foo' },
  { prop: 'bar' },
  { prop: 'baz' }
];
const foundBar = arr.find((obj) => {
  console.log('iteration');
  return obj.prop === 'bar';
});

A throw will indeed break out of a .reduce (although you shouldn't use errors for control flow):

[1, 2, 3, 4, 5].reduce((a, num) => {
  console.log('iteration');
  if (num > 2) {
    throw new Error();
  }
});
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Returning the accumulator...isn't that, in other words (which for me makes more sense), to say "enough adding to the accumulator, just return it"? – coolpasta Jun 25 '19 at 06:05
  • Sure, if the accumulator happens to be the sort of thing that is continually added to or mutated, though occasionally it isn't. https://stackoverflow.com/questions/53390440/how-to-find-a-object-in-a-nested-array-using-recursion-in-js – CertainPerformance Jun 25 '19 at 06:28
1

If your codebase seems to frequently need breaking inside of a reduce, it might be a better idea to use a for loop instead. However, if you absolutely have to use reduce and need to break from inside of it, you can use one of the following options:

  • Return the current accumulator without changes on every element after the point where you need to break.
  • Use throw to break out of the reduce method, although this is not recommended.
  • Mutate the 4th argument of the reducer function, which is the array being iterated over. If you mutate it to an empty array, reduce will exit. Be careful with this, as it can have unwanted side effects.

reduce is designed to iterate over all of the elements in an array, therefore this is why it's not easy, common or recommended to break out of it. This is also why there are so many other array manipulation methods, as reduce can in theory replace all of them given the proper function, however it presents certain limitations that other array methods do not.

Angelos Chalaris
  • 6,611
  • 8
  • 49
  • 75