Why such recursion not getting stack-overflowed?

Let's look at each in turn.

const recSetTimeOut = () => {
  console.log('in recSetTimeOut');
  setTimeout(recSetTimeOut, 0)
};
recSetTimeOut();

This is not actually recursion. You are registering recSetTimeOut with the scheduler. When the browser's UI thread goes idle, it will pull the next waiting function off the list, an invoke it. The call stack never grows; the scheduler (native code) will always be at the top of a very short call stack. You can verify this by emitting an exception and checking its call stack.

  • This function isn't actually recursive; the stack does not grow.
  • It yields control back to the UI thread after each invocation, thereby allowing UI events to be processed.
  • The next invocation only occurs once the UI is done doing its thing and invokes the next scheduled task.
const recPromise = () => {
  console.log('in recPromise');
  Promise.resolve().then(recPromise);
}
recPromise();

This is effectively an infinite loop that refuses to ever yield control back to the UI. Every time the promise resolves, a then handler is immediately invoked. When that completes, a then handler is immediately invoked. When that completes... The UI thread will starve, and UI events will never be processed. As in the first case, the call stack does not grow, as each callback is made by what is effectively a loop. This is called "Promise chaining". If a promise resolves to a promise, that new promise is then invoked, and this does not cause the stack to grow. What it does do, though, is prevent the UI thread from doing anything.

  • Effectively an infinite loop.
  • Refuses to yield control back to the UI.
  • The call stack does not grow.
  • The next call is invoked immediately and with extreme prejudice.

You can confirm both stack traces are practically empty by using console.log((new Error()).stack).

Neither solution should result in a Stack Overflow exception, though this may be implementation-dependent; the browser's scheduler might function differently from Node's.

Tags:

Javascript