Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive async with and without sleep

Tags:

javascript

I have two versions of an async function

async function asyncRecurseOne(i){
    try{
        console.log(i)
        i = i +1;
        await asyncRecurseOne(i)
    }catch(ex){
        console.log(ex);
    }
}

asyncRecurseOne(0);

which results in maximum call stack size exceeded at around number 6300

6246
6247
6248
RangeError: Maximum call stack size exceeded
    at asyncRecurseOne (/home/amit/Projects/NodeJs/MJS/recurse.js:38:17)
    at asyncRecurseOne (/home/amit/Projects/NodeJs/MJS/recurse.js:36:15)

Now in another version, I do the following using a sleep method

let sleep = (time) => new Promise((resolve) => setTimeout(resolve, time))
async function asyncRecurseTwo(i){
    try{
        console.log(i)
        i = i +1;
        await sleep(100);
        await asyncRecurseTwo(i)
    }catch(ex){
        console.log(ex);
    }
}

And this function does not give the maximum call stack size to reach the issue, I ran on my system till number 20000 was logged.

How does the second function keep executing without reaching the maximum stack size issue?

like image 232
amitKumar Avatar asked May 19 '21 16:05

amitKumar


1 Answers

async functions execute synchronously, up until the point they hit an await, at which point they return a promise. Your first piece of code has its only await on this line:

await asyncRecurseOne(i)

To evaluate this line, it needs to call asyncRecurseOne, get the return value, and only then will it await. So it will synchronously recurse, and that next time through the function will do the same thing, building a bigger and bigger call stack until you get the exception. It never makes it to the await.

Your other case doesn't have this problem. It makes it to this line:

await sleep(100);

And sleep creates and returns a promise. Then it hits the await, and so your function returns a promise of its own. No increasing call stack. 100 milliseconds later, it resumes and recurses, but this new recursion has the same interruption and so the callstack doesn't keep growing.

like image 64
Nicholas Tower Avatar answered Nov 20 '22 10:11

Nicholas Tower