遇到一个需求,要求只要接口请求不成功就重试一次。
Nuxt.js 2.x ,在 ~/plugins/axios.js
文件中使用 Axios 的拦截器功能来实现请求失败时重新发送请求的逻辑:
在 ~/plugins/axios.js
文件中定义重试逻辑:
javascript
import axios from 'axios';
// 创建一个axios实例
const axiosInstance = axios.create();
// 请求拦截器
axiosInstance.interceptors.request.use(config => {
// 可以在这里添加配置信息
return config;
}, error => {
// 请求错误时的处理
return Promise.reject(error);
});
// 响应拦截器
axiosInstance.interceptors.response.use(response => {
// 请求成功的处理
return response;
}, 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++;
// 延迟一段时间后重发请求
const backoff = new Promise(resolve => {
setTimeout(() => resolve(), config.retryDelay || 1);
});
// 返回重发的Promise
return backoff.then(() => axiosInstance(config));
});
export default axiosInstance;
在 nuxt.config.js
文件中配置插件:
arduino
export default {
// ...
plugins: [
'@/plugins/axios'
],
// ...
}
使用(这里是单独设置接口的重新发送请求):
arduino
axios.post('/api/...', {
retry: 2, // 最大重试次数
retryDelay: 500 // 重试间隔时间/毫秒
})
我的实际项目中是直接在全局设置的,这样就不需要每个接口去设置了:
typescript
import { Context } from '@nuxt/types';
import axios,{ AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios';
// 创建一个axios实例
const axiosInstance = axios.create()
export default async function (ctx: Context) {
const $axios:any = ctx.app.$axios;
$axios.defaults.withCredentials = false; // 默认不携带cookie
$axios.defaults.timeout = 30 * 1000; // 超时 30 * 1000
// 请求失败重新发起请求
$axios.defaults.retry = 2 // 最大重发请求次数
$axios.defaults.retryCount = 0 // 已重发请求次数
$axios.defaults.retryDelay = 500 // 重新请求间隔时间
$axios.onRequest((config: AxiosRequestConfig) => {
const token: string = ctx.app.$cookies.get('access_token');
if (token && config.headers.common) {
config.headers.common.Authorization = token;
}
return config;
});
$axios.onResponse((response: AxiosResponse<any>): any => {
const { config, status } = response;
...
return response.data;
});
$axios.onError((error: AxiosError<any>) => {
const { status, config } = (error.response as any) || {};
console.log('error-config', error.config)
// 接口请求失败重新发起请求
if (config.retry && config.retryCount < config.retry) {
console.log("axios重新发送请求")
// 延迟一段时间后重发请求
const backoff = new Promise(resolve => {
setTimeout(() => resolve(""), config.retryDelay || 1);
});
config.retryCount++
// 返回重发的Promise
return backoff.then(() => axiosInstance(config))
}
return Promise.resolve({
code: '0',
message: 'API Error',
data: null,
});
});
}
console.log('error-config', error.config) 输出:
json
{
"url": "/api/你的接口地址",
"method": "post",
"data": "{}",
"headers": {
"Accept": "application/json, text/plain, */*",
"Authorization": "",
"DEVICE": "pc",
"Content-Type": "application/json;charset=utf-8"
},
"baseURL": "/",
"transformRequest": [null],
"transformResponse": [null],
"timeout": 30000,
"withCredentials": false,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"retry": 2, // 重试次数
"retryCount": 0,
"retryDelay": 500,
"axios-retry": {
"retryCount": 0,
"lastRequestTime": 1710836764162
}
}