How to avoid Maximum call stack size exceeded when returning a recurring call?

151 Views Asked by At

I have this small script:

const returnCount = (n: number): number => {
  if (n === 0) return 0;
  return returnCount(n - 1);
};

const result = returnCount(100000);

which crashes with

Project/src/2023/23/test.ts:2
  if (n === 0) return 0;
  ^
RangeError: Maximum call stack size exceeded
    at returnCount (Project/src/2023/23/test.ts:2:3)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)
    at returnCount (Project/src/2023/23/test.ts:3:10)

And I'm not sure why.

I would understand it if my method what something like

const returnCount = (n: number): number => {
  if (n === 0) return 0;
  return 0 + returnCount(n - 1);
};

Because it needs to wait for the result of returnCount(n - 1) before returning 0 + returnCount(n - 1).

But in the case of return returnCount(n - 1);, I thought the stack trace would be "shortcuted" since the result of returnCount(n) would be the result of returnCount(n - 1).

How to make it behave like that so I don't hit the RangeError: Maximum call stack size exceeded error?

2

There are 2 best solutions below

0
Jay Shah On

In Javascript When the code runs, all the things happen inside the call stack and firstly the global execution context is created. In the case of your recursion case, it is throwing so many functional execution context inside the call stack. So you can use a loop here instead of recursion for the bigger values.

   let result = 0;
  
   while (n !== 0) {
    n -= 1;
    result += 1;
   }
  
   return result;
   };

   const result = returnCount(100000);
8
Jatin Parmar On

Let's try to understand the following from your code and question.

Why does it crash?

Every browser (javascript runtime ) has a certain limit on call stack size. For example, in Firefox, it is 26441 (depending on your version). When this limit exceeds it throws an exception.

How to fix it?

A quick workaround would be to know the browser stack size and then you can conditionally prevent it like this.

GetStackSize=()=>{
   let count = 0;
    const fn=()=>{
         count++;
         fn();
        }
      try {
          fn();
      }catch(e) {

      }
    return count;
 }
let maxStack=GetStackSize();

const returnCount = (n: number): number => {

    //to avoid max limit exception
    if (n === 0 || n>maxStack) return 0;

     return returnCount(n - 1);
 };

 const result = returnCount(100000);

I hope this will be helpful.