Axios: 添加重试参数

创建于 2015-11-27  ·  23评论  ·  资料来源: axios/axios

我有一个 API,它不时返回ECONNRESET 。 所以我想重试这样的错误。 您是否计划向此库添加retry功能?

最有用的评论

@mericsson我在重试时太需要指数退避。 我整理了以下效果很好的内容。 你我想添加检查特定的错误/状态代码,因为这目前只是拦截并重试所有错误。

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);
    });
});

使用:

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

配置选项:
retry - 第一次请求失败后重试请求的次数。
retryDelay - 失败请求之间等待的毫秒数(默认为 1)。

在某个时候,我可能会在一个要点中使这个更可配置。

所有23条评论

这事有进一步更新吗?

我认为这是非常重要的。 这种情况可能是当我们为移动网络实现 Axios 时,用户将互联网源从 WiFi 切换到任何类型的移动连接。

我不认为这种功能应该在这个库中。 如果你需要这个,你可以为此创建一个拦截器。

@jtangelder任何想法它应该是什么样子?

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);

像这样的东西! 它会重试 500 个错误一次。

我同意@jtangelder这不属于核心库。 如图所示,这是拦截器的一个很好的用例。

@jtangelder @mzabriskie谢谢! 实际上它也是文档的好例子

+1 我希望这个例子更容易找到!

@jtangelder非常感谢您的片段

对代码段稍加修正,我认为返回的错误状态应该是 504 而不是 500。

@jtangelder非常有用的例子。

我想知道,关于如何用指数退避做某事的任何想法? 是否可以从retryFailedRequest返回承诺? 或者其他建议? 谢谢!

@jtangelder 中的例子应该包含在食谱页面中

您现在可以为此使用

我同意。 这真的应该是库的一部分,或者至少有更好的文档记录。

@mericsson我在重试时太需要指数退避。 我整理了以下效果很好的内容。 你我想添加检查特定的错误/状态代码,因为这目前只是拦截并重试所有错误。

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);
    });
});

使用:

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

配置选项:
retry - 第一次请求失败后重试请求的次数。
retryDelay - 失败请求之间等待的毫秒数(默认为 1)。

在某个时候,我可能会在一个要点中使这个更可配置。

@KyleRoss感谢您的代码,我对重试进行了调整,使其成为指数级

// 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);
    });

@KyleRoss感谢分享。

延迟可以越来越多地设置:

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

如果您想重试 4xx 或 5xx 请求,您需要像这样处理错误对象:

拦截您的请求:

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);
  });

拦截您的回复:

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

很棒的想法。 如果人们有兴趣,我将其中的一些内容汇总到一个 npm 模块中:
https://github.com/JustinBeckwith/retry-axios

很高兴接受功能请求✨

axios-retry vs retry-axios

@KyleRoss我尝试将 retry 和 retryDelay 配置选项添加到 AxiosRequestConfig 但它看起来不存在。 你是如何让它发挥作用的?

@lawloretienne您需要确保在使用任何重试参数之前在我的示例中添加代码。 因为它更像是一个插件,新的属性没有被记录为 axios 本身的一部分。

config.__retryCount = config.__retryCount || 0;

@KyleRoss无法传递配置配置,每个 'config.__reyCount' 都未定义。
https://github.com/axios/axios/blob/v0.19.0/lib/core/mergeConfig.js
自定义属性现在被过滤掉了。

@dennisreimann自定义配置现在在 v0.19 中被过滤掉了,现在我们可以像这样传递配置:

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

@mericsson我在重试时太需要指数退避。 我整理了以下效果很好的内容。 你我想添加检查特定的错误/状态代码,因为这目前只是拦截并重试所有错误。

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);
    });
});

使用:

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

配置选项:
retry - 第一次请求失败后重试请求的次数。
retryDelay - 失败请求之间等待的毫秒数(默认为 1)。

在某个时候,我可能会在一个要点中使这个更可配置。

感谢帮助!

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

samayo picture samayo  ·  3评论

shaosh picture shaosh  ·  3评论

c0debreaker picture c0debreaker  ·  3评论

Baoyx007 picture Baoyx007  ·  3评论

ghost picture ghost  ·  3评论