Roy Wang
Roy Wang

Reputation: 11260

Repeat async function indefinitely without recursion/Promise

I want to repeatedly call an async function once it completes execution.
The async function invokes its callback argument upon completion, so I can accomplish this by recursively calling the function with the callback:

const fn = () => asyncFn(fn);

However, since NodeJS has stopped supporting tail call optimization, this method will eventually cause stack overflow.

A better way is to use ES6 Promise:

async function fn() {
  while (true) {
    await new Promise(asyncFn);
  }
}

Is there any other way to do it? How would it be done before the introduction of Promise?

Upvotes: 1

Views: 3271

Answers (1)

Mark
Mark

Reputation: 92440

I think your initial assumption about the recursive function is incorrect. When you call an async function the callback is queued and the function continues and returns. Once the async function resolves the function is called again, but this is after it has already returned so the stack doesn't wind up.

You can see that here where we get the start and end of the function:

const runAsync = () => {
    console.log("starting async function")
    setTimeout(() => {
        let v = runAsync()
        console.log("return val", v)
    }, 1000)
    return "async function return"
}
  
console.log("return: ", runAsync())

If the stack was winding up with this, you would never see the return value. You would just see the logs starting async function for each call. This is the behavior seen here where the stack does overflow:

const recursiveFn = () => {
    console.log("starting function")
    let v = recursiveFn()
    console.log("return val", v)
    return "test"  // never gets here
}

console.log("return: ", recursiveFn())

Upvotes: 5

Related Questions