New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Retry Parameter #164

Closed
hyzhak opened this Issue Nov 27, 2015 · 17 comments

Comments

Projects
None yet
@hyzhak

hyzhak commented Nov 27, 2015

I have one API that time to time returns ECONNRESET. So I'd like to do retry on such an error. Do you have plans to add retry feature to this library?

@incubus8

This comment has been minimized.

incubus8 commented Dec 10, 2015

any update on this?

I think this is very important. The scenario maybe when we implement Axios for mobile web, then the user switch the internet source from WiFi to any kind of mobile connection.

@jtangelder

This comment has been minimized.

Contributor

jtangelder commented Dec 21, 2015

I don't think this kind of functionality should be in this library. If you need this, you can create a interceptor for this.

@hyzhak

This comment has been minimized.

hyzhak commented Dec 21, 2015

@jtangelder any ideas how should it look like?

@jtangelder

This comment has been minimized.

Contributor

jtangelder commented Dec 22, 2015

function retryFailedRequest (err) {
  if (err.status === 500 && err.config && !err.config.__isRetryRequest) {
    err.config.__isRetryRequest = true;
    return axios(err.config);
  }
  throw err;
}
axios.interceptors.response.use(undefined, retryFailedRequest);

Something like this! It retries 500 errors once.

@mzabriskie

This comment has been minimized.

Member

mzabriskie commented Dec 23, 2015

I agree with @jtangelder that this doesn't belong in the core library. This is a great use case for interceptors as illustrated.

@hyzhak

This comment has been minimized.

hyzhak commented Dec 24, 2015

@jtangelder @mzabriskie thanks! actually it is great example for documentation too

@dmt0

This comment has been minimized.

dmt0 commented Jan 14, 2016

+1 I wish this example was easier to find!

@incubus8

This comment has been minimized.

incubus8 commented Mar 1, 2016

@jtangelder thanks a lot for the snippet

A little correction on the snippet, I think the returned error status should be 504 instead of 500.

@mericsson

This comment has been minimized.

mericsson commented Jun 21, 2016

@jtangelder very helpful example.

I'm wondering, any ideas on how to do something with exponential backoff? Is it possible to return a promise from retryFailedRequest? Or other suggestions? Thanks!

@AlahmadiQ8

This comment has been minimized.

AlahmadiQ8 commented Jul 27, 2016

The example in @jtangelder should be included in the cookbook page

@rubennorte

This comment has been minimized.

Member

rubennorte commented Nov 14, 2016

You can now use axios-retry for this.

@chuckhacker

This comment has been minimized.

chuckhacker commented Jan 23, 2017

I agree. This should really be a part of the library, or at least better-documented.

@KyleRoss

This comment has been minimized.

KyleRoss commented Sep 7, 2017

@mericsson I am too in need of exponential backoff when retrying. I've put together the following which works great. You my want to add in checking for specific errors/status codes as this currently just intercepts and retries all errors.

axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
    var config = err.config;
    // If config does not exist or the retry option is not set, reject
    if(!config || !config.retry) return Promise.reject(err);
    
    // Set the variable for keeping track of the retry count
    config.__retryCount = config.__retryCount || 0;
    
    // Check if we've maxed out the total number of retries
    if(config.__retryCount >= config.retry) {
        // Reject with the error
        return Promise.reject(err);
    }
    
    // Increase the retry count
    config.__retryCount += 1;
    
    // Create new promise to handle exponential backoff
    var backoff = new Promise(function(resolve) {
        setTimeout(function() {
            resolve();
        }, config.retryDelay || 1);
    });
    
    // Return the promise in which recalls axios to retry the request
    return backoff.then(function() {
        return axios(config);
    });
});

To use:

axios.get('/some/endpoint', { retry: 5, retryDelay: 1000 })
    .then(function(res) {
        console.log('success', res.data);
    })
    .catch(function(err) {
        console.log('failed', err);
    });

Config Options:
retry - Number of times to retry the request after first failed request.
retryDelay - Number of milliseconds to wait in between failed requests (defaults to 1).

I may make this a bit more configurable in a gist at some point.

@akhayoon

This comment has been minimized.

akhayoon commented Nov 6, 2017

@KyleRoss Thanks for the code, I made an adjustment for the retries to be exponential

// Create new promise to handle exponential backoff. formula (2^c - 1 / 2) * 1000(for mS to seconds)
    const backOffDelay = config.retryDelay 
        ? ( (1/2) * (Math.pow(2, config.__retryCount) - 1) ) * 1000
        : 1;

    const backoff = new Promise((resolve) => {
        setTimeout(() => {
            resolve();
        },  backOffDelay);
    });
@mkhahani

This comment has been minimized.

mkhahani commented Dec 7, 2017

@KyleRoss Thanks for sharing.

The delay can be set increasingly:

const RETRY_TIMEOUTS = [1, 3, 5, 10]; // seconds
const delay = RETRY_TIMEOUTS[config.retryCount] * 1000;
@rimiti

This comment has been minimized.

rimiti commented Jan 20, 2018

If you want to retry an 4xx or 5xx request, you need work with the error object like that:

To intercept your requests:

axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

To intercept your responses:

axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });
@JustinBeckwith

This comment has been minimized.

Collaborator

JustinBeckwith commented Jan 30, 2018

Awesome ideas. I rolled a fair bit of this up into an npm module, if folks are interested:
https://github.com/JustinBeckwith/retry-axios

Happy to take feature requests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment