前端Axios失败重试
失败重试次数写在vite全局配置中,之后统一修改即可
vite环境变量
properties
# 失败重试次数
VITE_BASE_API_RETRY=5
# 失败重试时间
VITE_BASE_API_RETRY_DELAY=3000
Axios重试
思路
- 在Axios创建中读取vite环境变量配置,将其赋值
- 在发送请求时,如果出错不返回也就是不
return
之后设置定时器去重试之前的请求 - 写在Axios中好处是不用一个一个去配置了
- 当重试次数大于约定次数则返回
- 如果期间成功了就回到主页
未解决问题
- 本来想的是,如果失败了就跳转到失败页这样在失败页中做一些失败的显示,比如重试次数之类显示
- 如果使用
windows.lcoation
方式跳转,在我的谷歌浏览器中会将进行弹窗拦截无法实现跳转,解决无法跳转问题移入vuerouter- 如果请求成功后本来想的是,成功就返回上一次页面,但是会出现页面跳来跳去问题只能让它成功后跳转到固定页面
- 因为自定义的配置Axios不支持会报错
Vue: Object literal may only specify known properties, and 'retry' does not exist in type 'CreateAxiosDefaults<any>'.
定义Axios变量
在创建请求时将重试次数和时间放入到Axios配置中
ts
const request = axios.create({
// 默认请求地址
baseURL: import.meta.env.VITE_BASE_API,
// 设置超时时间
timeout: import.meta.env.VITE_BASE_API_TIMEOUT,
retry: import.meta.env.VITE_BASE_API_RETRY, //设置全局重试请求次数(最多重试几次请求)
retryDelay: import.meta.env.VITE_BASE_API_RETRY_DELAY, //设置全局请求间隔
// 跨域允许携带凭证
// withCredentials: true,
});
失败重试
失败的emit
在error.config
中可以获取到之前在Axios配置中的变量
使用全局总线在/500
页面中接受失败的次数以及是否成功
ts
async error => {
const config = error.config;
// 重试次数
const retry = config.retry;
// 重试时间
const retryDelay = config.retryDelay;
// 当前重试次数
config._retryCount = config._retryCount || 0;
// 如果重试次数大于定义次数返回错误
if (config._retryCount > retry) {
return Promise.reject(new Error(error.response.statusText));
}
// 失败后打开到500页面
await router.push('/500');
mittBus.emit('system-request-error', { retry, retryCount: config._retryCount, isSuccess: false });
// 设置请求间隔 在发送下一次请求之前停留一段时间,时间为上方设置好的请求间隔时间
const backoff = new Promise(function (resolve) {
setTimeout(() => resolve(true), retryDelay || 1000);
});
// 如果失败次数加1
config._retryCount += 1;
// 再次发送请求
return backoff.then(() => request(error.config));
}
成功的emit
如果成功使用全局事件总线,在错误页面接受之后跳转
ts
(response: any) => {
// 返回消息内容
mittBus.emit('system-request-error', { retry: 0, retryCount: 0, isSuccess: true });
return data;
}
错误页
ts
<template>
<div class="not-container">
<img alt="500" class="not-img" src="@/assets/images/tip1/500.png" />
<div class="not-detail">
<h2>500</h2>
<h4 v-if="isReTry">抱歉,您的网络不见了~🤦♂️🤦♀️</h4>
<h4 v-else class="mt-0 mb-2">您的网络不见了~ 正在重试 {{ retryCount }}/{{ retry }}</h4>
<button @click="router.push(HOME_URL)">返回首页</button>
</div>
</div>
</template>
<script lang="ts" setup>
import { HOME_URL } from '@/enums/constant/route.ts';
import { useRouter } from 'vue-router';
import { onMounted, ref } from 'vue';
import mittBus from '@/utils/mittBus.ts';
const router = useRouter();
const retry = ref(import.meta.env.VITE_BASE_API_RETRY);
const retryCount = ref(0);
const isReTry = ref(false);
/**
* * 监听失败消息
*/
const onListenSystemRequestError = () => {
mittBus.on('system-request-error', (value: any) => {
if (value.isSuccess) {
router.push('/');
// router.go(-1);
}
retry.value = value.retry;
retryCount.value = value.retryCount;
if (parseInt(retry.value) === retryCount.value) {
isReTry.value = true;
}
});
};
onMounted(() => {
onListenSystemRequestError();
});
</script>
<style lang="scss" scoped>
@import url('index.scss');
</style>
全部Axios代码
ts
import { Message } from '@/components/Message/Message.tsx';
import router from '@/router';
import { localGet, localRemove } from '@/utils/util.ts';
import axios from 'axios';
import mittBus from '@/utils/mittBus.ts';
const request = axios.create({
// 默认请求地址
baseURL: import.meta.env.VITE_BASE_API,
// 设置超时时间
timeout: import.meta.env.VITE_BASE_API_TIMEOUT,
retry: import.meta.env.VITE_BASE_API_RETRY, //设置全局重试请求次数(最多重试几次请求)
retryDelay: import.meta.env.VITE_BASE_API_RETRY_DELAY, //设置全局请求间隔
// 跨域允许携带凭证
// withCredentials: true,
});
// 请求拦截器
request.interceptors.request.use(config => {
// 当本地有token表示登录了,请求时将token带上
const token = localGet('token');
if (token !== null) {
config.headers['token'] = token;
}
return config;
});
// 响应拦截器
request.interceptors.response.use(
(response: any) => {
// 返回相应数据
const data = response.data;
// 登录过期
if (data.code === 208) {
Message.warning(data.message);
router.push('/').then();
localRemove('token');
}
// 账户被封禁
if (data.code === 209) {
Message.warning(data.message);
router.push('/').then();
localRemove('token');
}
// 统一处理异常
if (data.code !== 200 && data.code < 300) {
Message.warning(data.message);
} else if (data.code > 300) {
Message.error(data.message);
}
// 返回消息内容
mittBus.emit('system-request-error', { retry: 0, retryCount: 0, isSuccess: true });
return data;
},
async error => {
const config = error.config;
// 重试次数
const retry = config.retry;
// 重试时间
const retryDelay = config.retryDelay;
// 当前重试次数
config._retryCount = config._retryCount || 0;
// 如果重试次数大于定义次数返回错误
if (config._retryCount > retry) {
return Promise.reject(new Error(error.response.statusText));
}
// 失败后打开到500页面
await router.push('/500');
mittBus.emit('system-request-error', { retry, retryCount: config._retryCount, isSuccess: false });
// 设置请求间隔 在发送下一次请求之前停留一段时间,时间为上方设置好的请求间隔时间
const backoff = new Promise(function (resolve) {
setTimeout(() => resolve(true), retryDelay || 1000);
});
// 如果失败次数加1
config._retryCount += 1;
// 再次发送请求
return backoff.then(() => request(error.config));
},
);
export default request;