Axios 超时重新请求实现方案
在 Axios 中实现超时重新请求可以通过以下几种方式:
1. 使用拦截器实现自动重试
import axios from 'axios';
// 创建axios实例
const instance = axios.create();
// 设置超时时间
instance.defaults.timeout = 5000;
// 最大重试次数
const MAX_RETRY = 3;
// 添加请求拦截器
instance.interceptors.response.use(undefined, (error) => {
const config = error.config;
// 如果配置不存在或未设置重试选项,则拒绝
if (!config || !config.retry) return Promise.reject(error);
// 设置重试次数变量
config.__retryCount = config.__retryCount || 0;
// 检查是否已达到最大重试次数
if (config.__retryCount >= config.retry) {
return Promise.reject(error);
}
// 增加重试计数器
config.__retryCount += 1;
// 创建新的Promise来处理指数退避
const backoff = new Promise((resolve) => {
setTimeout(() => {
resolve();
}, config.retryDelay || 1000);
});
// 返回Promise,在退避时间后重试请求
return backoff.then(() => instance(config));
});
// 使用示例
instance.get('/api/data', {
retry: MAX_RETRY, // 重试次数
retryDelay: 1000 // 重试延迟时间(毫秒)
}).then(response => {
console.log(response.data);
}).catch(error => {
console.error('请求失败:', error);
});
2. 封装请求函数实现重试
function requestWithRetry(url, options = {}, retryCount = 3) {
return new Promise((resolve, reject) => {
const attempt = (currentRetry) => {
axios({
url,
...options,
timeout: options.timeout || 5000
})
.then(resolve)
.catch((error) => {
if (currentRetry <= 0 || !isRetryable(error)) {
return reject(error);
}
console.log(`请求失败,剩余重试次数: ${currentRetry - 1}`);
// 指数退避
const delay = Math.pow(2, retryCount - currentRetry) * 1000;
setTimeout(() => {
attempt(currentRetry - 1);
}, delay);
});
};
attempt(retryCount);
});
}
// 判断错误是否可重试
function isRetryable(error) {
return (
error.code === 'ECONNABORTED' || // 超时
!error.response || // 无响应(网络错误)
error.response.status >= 500 // 服务器错误
);
}
// 使用示例
requestWithRetry('/api/data', { method: 'get' }, 3)
.then(response => console.log(response.data))
.catch(error => console.error('最终失败:', error));
3. 使用第三方库
也可以使用专门处理重试的库,如 axios-retry
:
import axios from 'axios';
import axiosRetry from 'axios-retry';
// 配置axios-retry
axiosRetry(axios, {
retries: 3, // 重试次数
retryDelay: (retryCount) => {
return retryCount * 1000; // 重试延迟
},
retryCondition: (error) => {
// 只在超时或5xx错误时重试
return axiosRetry.isNetworkOrIdempotentRequestError(error) ||
error.code === 'ECONNABORTED';
}
});
// 正常使用axios
axios.get('/api/data', { timeout: 5000 })
.then(response => console.log(response.data))
.catch(error => console.error('请求失败:', error));
注意事项
- 幂等性:确保请求是幂等的(GET、HEAD、OPTIONS、PUT、DELETE等),POST请求重试可能导致重复操作
- 退避策略:建议使用指数退避策略,避免同时重试大量请求
- 用户体验:对于前端应用,应考虑用户等待时间,不宜设置过多重试次数
- 取消请求:如果用户导航离开页面,应取消未完成的请求
以上方案可以根据实际需求进行调整和组合使用。