Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why recursive async functions in Javascript lead to stack overflow?

Consider this snippet:

function f() {
  return new Promise((resolve, reject) => {
    f().then(() => {
      resolve();
    });
  });
}

f();

which can also be written like this:

async function f() {
  return await f();
}

f();

If you run any of the given two codes, you'll face this error:

(node:23197) UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded

My question is why? Before answering my question, please consider my argument:

I understand the concept of recursion and how it leads to a stack overflow if there's no stopping condition. But my argument here is that once the first f(); is executed, it will return a Promise and it exits the stack so this recursion should not face any stack overflow ever. To me, this should behave the same as:

while (1) {}

Of course, if I write it like this, it will be fixed:

function f() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      f().then(() => {
        resolve();
      });
    }, 0);
  });
}

f();

which is a different story and I have no problem with it.

[UPDATE]

My bad, I forgot to mention I was testing with node v8.10.0 on the server side.

like image 902
Mehran Avatar asked Jul 03 '19 23:07

Mehran


Video Answer


1 Answers

Why would you not expect it to cause infinite recursion? The constructor of the promise is calling f recursively so the promise never gets to construct as an infinite recursion loop occurs before the promise is constructed.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

From the link above

The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object).

like image 136
Adrian Brand Avatar answered Oct 26 '22 16:10

Adrian Brand