Vincent Miller
Vincent Miller

Reputation: 21

How do to do recursive async/await in Javascript?

I have the following code, stripped out of any specifics:

const installation = async() => {
  try {
    const call = await callToServer();
    
    if('finished' in call) {
      return call;
    } else {
      await callToServer();
    }
  } catch(e) {
  //
  }
}

And as you can see, I'd like to recursively call callToServer until I see finished inside its response. I understand why my code isn't working and why it's making only 2 calls (or 1, if it sees finished on the first run), but I don't know how to make it recursive.

I tried with a for loop and, well, it worked as-is, but in my case, I don't know the number of calls I need to make upfront. So I went to a do...while loop, since it seemed to fit:

do {
    const call = await callToServer();
} while(!('finished' in call));

But this only runs once. It sees that the while(!... doesn't actually know about call. How can I make it work?

Upvotes: 0

Views: 4747

Answers (4)

Louay Al-osh
Louay Al-osh

Reputation: 3405

Notice that using async/await is new syntax in ES that is similar to how generators function* and yield work, so we can do for, while, recursive call for async function in a sync syntax.

Here is an example that do recursive call while the target value is not met yet


let counter = 0;
let res;


function delay(ms){
        return new Promise((res,rej) => setTimeout(res, ms));
}

async function callToServer(){
        await delay(100);
        return ++counter;
}







async function recursive(){

        res = await callToServer();
        console.log(`called server with return value = ${res}`);

        if(res < 10){
                return await recursive();
        }

        return 'RESULT';

}


(async function main(){
                
        let finalRes = await recursive();
        console.log(finalRes);

})()

this code will output:

called server with return value = 1
called server with return value = 2
called server with return value = 3
called server with return value = 4
called server with return value = 5
called server with return value = 6
called server with return value = 7
called server with return value = 8
called server with return value = 9
called server with return value = 10
RESULT

Upvotes: 0

Jamiec
Jamiec

Reputation: 136094

You don't necessarily need recursion, a simple loop will work to recall your callToServer.

You were on the right track with a do...while loop. You might consider putting a limit in on the number of calls before bombing out. The below will attempt 10 times before doing so - it uses a random chance on whether it works or not so you might see it bombing out.

const installation = async() => {
  try {
    var call = null;
    var i = 0
    do {
       console.log("attempt",i++)
       call = await callToServer();
    } while(! ('finished' in call) && i <10 );
    return call;
  } catch(e) {
  //
  }
}

const callToServer = async() => {
  return new Promise(resolve => {
    if(Math.random()>0.95) {
      resolve({finished:true})
    }
    else {
      resolve({notfinished:true})
    }
  })
}

const test = async() => {
  var res = await installation()
  console.log(res)
}

test()

Upvotes: 0

P.B.UDAY
P.B.UDAY

Reputation: 483

  const installation = async() => {
  try {
    const call = await callToServer();
    
    if('finished' in call) {
      return call;
    } else {
      return await installation();
    }
  } catch(e) {
  //
  }
}

Upvotes: 0

Buh Buh
Buh Buh

Reputation: 7545

} else {
  return await installation();
}

A recursive function would call the entire function again.

Upvotes: 6

Related Questions