Skip to content
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 · 23 comments
Closed

Adding Retry Parameter #164

hyzhak opened this issue Nov 27, 2015 · 23 comments

Comments

@hyzhak
Copy link

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?

@rhzs
Copy link

rhzs 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
Copy link
Contributor

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
Copy link
Author

hyzhak commented Dec 21, 2015

@jtangelder any ideas how should it look like?

@jtangelder
Copy link
Contributor

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
Copy link
Member

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

@hyzhak
Copy link
Author

hyzhak commented Dec 24, 2015

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

@dmt0
Copy link

dmt0 commented Jan 14, 2016

+1 I wish this example was easier to find!

@rhzs
Copy link

rhzs 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
Copy link

@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
Copy link

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

@rubennorte
Copy link
Member

You can now use axios-retry for this.

@chuckhacker
Copy link

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

@KyleRoss
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link
Collaborator

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 ✨

@moffsugita
Copy link

axios-retry vs retry-axios

@lawloretienne
Copy link

lawloretienne commented Jan 21, 2019

@KyleRoss I tried adding the retry and retryDelay configuration options to AxiosRequestConfig but it doesnt look like they exist. How did you get that to work?

@KyleRoss
Copy link

@lawloretienne you need you make sure you add the code in my example prior to using any of the retry parameters. Since it acts more like a plugin, the new properties are not documented as part of axios itself.

@adntin
Copy link

adntin commented Jul 4, 2019

config.__retryCount = config.__retryCount || 0;

@KyleRoss Unable to pass config config, each 'config.__reyCount' is undefined.
https://github.com/axios/axios/blob/v0.19.0/lib/core/mergeConfig.js
Custom properties are now filtered out.

@mistake1px
Copy link

@dennisreimann custom config are now filtered out in v0.19, and now we can pass config like this:

axios.defaults.headers.common['retry'] = 3
axios.defaults.headers.common['retryDelay'] = 1000
axios.defaults.headers.common['retryCount'] = 0

@spongege
Copy link

@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.

thanks for help!

@axios axios locked and limited conversation to collaborators May 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests