业务场景:在某些情况下,比如请求超时的时候,我们希望能自动重新发起请求进行重试操作,从而完成对应的操作。例如在项目中,用户发起的请求可能会因为网络不稳定都要,接口有时候会返回异常,这时候就需要进行请求重试而避免用户需要去重复操作,当然也要有重复次数的配置,不能一直去请求重试。
一、拦截器实现请求重试的方案
Axios 提供了 请求拦截器和响应拦截器 来分别处理请求和响应,它们的作用如下:
- 请求拦截器:该类拦截器的作用是在请求发送前统一执行某些操作,比如在请求头中添加 token 字段。
- 响应拦截器:该类拦截器的作用是在接收到服务器响应后统一执行某些操作,比如发现响应状态码为 401 时,自动跳转到登录页。 在 Axios 中设置拦截器很简单,通过
axios.interceptors.request
和axios.interceptors.response
对象提供的use
方法,就可以分别设置请求拦截器和响应拦截器:
typescript
export interface AxiosInstance {
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
}
export interface AxiosInterceptorManager<V> {
use(onFulfilled?: (value: V) => V | Promise<V>,
onRejected?: (error: any) => any): number;
eject(id: number): void;
}
对于请求重试的功能来说,我们希望让用户不仅能够设置重试次数,而且可以设置重试延时时间。当请求失败的时候,若该请求的配置对象配置了重试次数,而 Axios 就会重新发起请求进行重试操作。为了能够全局进行请求重试,接下来我们在响应拦截器上来实现请求重试功能,具体代码如下所示:
javascript
axios.interceptors.response.use(null, (err) => {
let config = err.config;
if (!config || !config.retryTimes) return Promise.reject(err);
const { __retryCount = 0, retryDelay = 300, retryTimes } = config;
// 在请求对象上设置重试次数
config.__retryCount = __retryCount;
// 判断是否超过了重试次数
if (__retryCount >= retryTimes) {
return Promise.reject(err);
}
// 增加重试次数
config.__retryCount++;
// 延时处理
const delay = new Promise((resolve) => {
setTimeout(() => {
resolve();
}, retryDelay);
});
// 重新发起请求
return delay.then(function () {
return axios(config);
});
});
以上的代码并不会复杂,对应的处理流程如下图所示: