Axios Async/Await with Retry

Yogi Saputro - Mar 9 '21 - - Dev Community

If you have been coding javascript for a while, you'd probably have known about Axios. It is a famous JS library for making HTTP request. Whether you are back-end or front-end developer, Axios is essential to access API services out there.

Alas, reliability is scarce even when we're in 2020s. Things happen, and your HTTP request might get stalled. So what do we do? In some cases, we will try again until we get the data we need. In those cases, equipping Axios with retry capability is necessary.

In this post, I'm going to show how to equip Axios with retry capability i.e resend HTTP request when server doesn't answer. First, the native way. Then, we're going to use some libraries.

I feel the need to write this tutorial since most examples of Axios are written in .then pattern. I'm accustomed to async/await pattern since it feels more familiar (especially if you learn other OOP languages). Performance-wise, both are internally equal.

Anyway, let's dive in to our code. I'm going to make a Node.JS project. Feel free to use whatever javascript stuff to suit your needs. Also, make sure your dependencies are fulfilled. I already installed Node.JS and NPM for this tutorial.

First, make new project using Terminal.

$ mkdir request-retry
$ cd request-retry
$ npm init -y
$ touch index.js
Enter fullscreen mode Exit fullscreen mode

Then, install axios package.

$ npm install axios
Enter fullscreen mode Exit fullscreen mode

Now, we're going to edit index.js using code editor. I'm going to make HTTP request to https://mock.codes and see if it responds.

const axios = require('axios')

const myRequest = async () => {
  try {
    const myConfig = {
      headers: {
        Authorization: 'Basic lorem12345'
      }
    }

    const req = await axios.get('https://mock.codes/200', myConfig);
    console.log(req.data);
  } catch (error) {
    console.log(error.response.data);
  }
}

myRequest();
Enter fullscreen mode Exit fullscreen mode

Now, run index.js

$ node index.js
Enter fullscreen mode Exit fullscreen mode

and we will get this result

{ statusCode: 200, description: 'OK' }

Things are okay, right? Now, I'm going to rig this HTTP request by setting an unreasonably low timeout. To do that, add timeout in the request config. Let's check index.js again and edit myConfig so it looks like this.

    const myConfig = {
      headers: {
        Authorization: 'Basic lorem12345'
      },
      timeout: 10 // 10ms timeout so servers hate you
    }
Enter fullscreen mode Exit fullscreen mode

If I run $ node index.js again, I'll probably get something like this.

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'data' of undefined

What happened? Due to unfinished request, req doesn't get data from server. Therefore, its value is undefined. We can't get keys from undefined, hence the error.

It is time to implement Axios with retry capability. But before going any further, I want to make clear when referring to retry, mostly we want to have control over two things:

  • How many times we want to retry
  • how long we want to wait for each trial

There are two main ways to do this:

  1. Implement directly
  2. Use package

Direct Implementation

This option means doing everything from scratch. It's not too difficult, though. It is suitable option when we just need few types of request in our code and adding package would burden the app.

One simple approach is enveloping every request with loop. Now let's say I'm willing to retry 3 times and 50 miliseconds for each request. This is the example of working code.

const axios = require('axios');

const myRequest = async () => {
  try {
    const retries = 3 // amount of retries we're willing to do
    const myConfig = {
      headers: {
        Authorization: 'Basic lorem12345'
      },
      // we're willing to wait 50ms, servers still hate you
      timeout: 50 
    }
    for (var i=0; i<retries; i++) {
      try {
        const req = await axios.get('https://mock.codes/200', myConfig);
        if (req) {
          console.log(req.data);
          break;
        } else {
          console.log('cannot fetch data');
        }
      } catch (error) {
        console.log('cannot fetch data');
      }
    }
  } catch (e) {
    console.log(e);
  }

  myRequest();
}
Enter fullscreen mode Exit fullscreen mode

It's quite long, but if we're not doing it often across one project, this solution fits nicely.

Use Package

There are times when we have to connect to many endpoints with different characteristics. In such circumstance, using package is justified.

There are 3 famous packages that satisfy our needs:

  1. retry, a general purpose retry operation.
  2. axios-retry, most popular retry add-on for Axios
  3. retry-axios, second most popular retry add-on for Axios

I will use retry-axios since it provides easier implementation on async/await pattern. Now don't forget to read on its documentation. Also, don't forget to install it using Terminal.

$ npm install retry-axios
Enter fullscreen mode Exit fullscreen mode

This is an example of working code.

const rax = require('retry-axios');
const axios = require('axios');

rax.attach();
const myRequest = async () => {
  try {
    const myConfig = {
      raxConfig: {
        retry: 5, // number of retry when facing 4xx or 5xx
        noResponseRetries: 5, // number of retry when facing connection error
        onRetryAttempt: err => {
          const cfg = rax.getConfig(err);
          console.log(`Retry attempt #${cfg.currentRetryAttempt}`); // track current trial
        }
      },
      timeout: 50 // don't forget this one
    }
    const req = await axios.get('https://mock.codes/200', myConfig);
    console.log(req.data);
  } catch (error) {
    console.log(error);
  }
}

myRequest();
Enter fullscreen mode Exit fullscreen mode

Instead of doing loop, I basically attach retry-axios object to Axios. My part is handling config for the request. It is much simpler and delivers same result as direct implementation.

That's it! Now we can make Axios more reliable in sending HTTP request.

Do you find it useful, informative, or insightful ?
Do you find mistakes in my tutorial ?
Do you have any questions?
Feel free to comment below 👇 and let me know.

. . . . . . . .
Terabox Video Player