我有一个 API,它不时返回ECONNRESET
。 所以我想重试这样的错误。 您是否计划向此库添加retry
功能?
这事有进一步更新吗?
我认为这是非常重要的。 这种情况可能是当我们为移动网络实现 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)。在某个时候,我可能会在一个要点中使这个更可配置。
感谢帮助!
最有用的评论
@mericsson我在重试时太需要指数退避。 我整理了以下效果很好的内容。 你我想添加检查特定的错误/状态代码,因为这目前只是拦截并重试所有错误。
使用:
配置选项:
retry
- 第一次请求失败后重试请求的次数。retryDelay
- 失败请求之间等待的毫秒数(默认为 1)。在某个时候,我可能会在一个要点中使这个更可配置。