0

I'm using promises (with await). I have an async function that has to await an async request: an http request for example. The HTTP request can fail (timeout or other motivations) but I need to recall it until success or until a max number of attempts are done (let's say n attempts) and then continue the execution of the function. I wasn't able to find a clean and well organized way to do this. Below a pseudocode:

async function func(){
  //DO something before HTTP request
  try{
    let res = await http_request();
  } catch(e){
    //http request failed
    //WHAT TO DO HERE TO CALL AGAIN THE HTTP REQUEST until success??
    //or until max attempts == n?
  }
  //DO other stuff only after the http request succeeded
  return;
}

the idea would be to return at the end a promise which resolves if the http requests and the rest of the code succeeded or rejects if the http request attempts failed n times or other errors.

PS: the http request is an example but http_request() can be substituted with any other async function.

3 Answers 3

2

you could do a while loop that breaks once a successful request is made, and otherwise tries again. a counter can be used to limit the number of attemps.

async function func(){
  let counter = 0;
  while (counter < 100) {
    try{
      let res = await http_request();
      break;
    } catch(e){
      counter++
      continue;
    }
  }
  return;
}
Sign up to request clarification or add additional context in comments.

1 Comment

I was thinking to fancy stuff, but probably this is the cleanest and easiest solution :) I'll just need to handle different errors in the catch and continue the while only in case of some failures.
2

You can just call your function again to retry and you can pass it a retry counter. You should also probably insert a short delay before retrying to avoid hammering a busy server.

function delay(t, v) {
   return new Promise(resolve => {
       setTimeout(resolve.bind(null, v), t);
   });
}

const kMaxAttempts = 10;
const kDelayBeforeRetry = 500;

async function func(cntr = 0){
  //DO something before HTTP request
  ++cntr;
  try{
    let res = await http_request();
    //DO other stuff only after the http request succeeded
    return finalValue;
  } catch(e){
    // test to see if max retries have been exceeded
    // also examine e to see if the error is retryable
    if (cntr > kMaxAttempts || e is not a retryable error) {
        throw e;
    }
    // retry after a short delay
    return delay(kDelayBeforeRetry, cntr).then(func);

  }
}

Comments

0

I would treat the request differently. You're trying to catch only an error. You also need to handle a failed response. Which ever request API you you are using, http_request() will most likely return a response and an error object. You can check for failed requests with something like response.status === 500. If the response has failed for whatever reason, you can then retry the request. I frequently see it done like this

http_request.GET(URL).then((response, error) => {
  if (error) // retry
  else if (response.status === 200 && response.body) // success
  else if (response.status === 500) // retry
})

As for the actual code, you can make a reusable request function that does the if / else error handling and takes a HTTP method and some options and data etc. and returns a promise of your data or error -- that is another common pattern.

1 Comment

Yeah, of course I need to handle different responses and try again only in some cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.