未验证 提交 136cbb1e 编写于 作者: C Captain 提交者: GitHub

feat: add request retry (#1553)

上级 78535bdd
......@@ -111,4 +111,12 @@ export default [
return resultSuccess(undefined, { message: 'Token has been destroyed' });
},
},
{
url: '/basic-api/testRetry',
statusCode: 405,
method: 'get',
response: () => {
return resultError('Error!');
},
},
] as MockMethod[];
......@@ -8,6 +8,7 @@ enum Api {
Logout = '/logout',
GetUserInfo = '/getUserInfo',
GetPermCode = '/getPermCode',
TestRetry = '/testRetry',
}
/**
......@@ -39,3 +40,16 @@ export function getPermCode() {
export function doLogout() {
return defHttp.get({ url: Api.Logout });
}
export function testRetry() {
return defHttp.get(
{ url: Api.TestRetry },
{
retryRequest: {
isOpenRetry: true,
count: 5,
waitTime: 1000,
},
},
);
}
......@@ -92,6 +92,7 @@ export default {
breadcrumb: 'Breadcrumbs',
breadcrumbFlat: 'Flat Mode',
breadcrumbFlatDetail: 'Flat mode details',
requestDemo: 'Retry request demo',
breadcrumbChildren: 'Level mode',
breadcrumbChildrenDetail: 'Level mode detail',
......
......@@ -88,6 +88,7 @@ export default {
ws: 'websocket测试',
breadcrumb: '面包屑导航',
breadcrumbFlat: '平级模式',
requestDemo: '测试请求重试',
breadcrumbFlatDetail: '平级详情',
breadcrumbChildren: '层级模式',
breadcrumbChildrenDetail: '层级详情',
......
......@@ -31,6 +31,15 @@ const feat: AppRouteModule = {
title: t('routes.demo.feat.ws'),
},
},
{
path: 'request',
name: 'RequestDemo',
// @ts-ignore
component: () => import('/@/views/demo/feat/request-demo/index.vue'),
meta: {
title: t('routes.demo.feat.requestDemo'),
},
},
{
path: 'session-timeout',
name: 'SessionTimeout',
......
......@@ -111,7 +111,10 @@ export class VAxios {
// Response result interceptor error capture
responseInterceptorsCatch &&
isFunction(responseInterceptorsCatch) &&
this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch);
this.axiosInstance.interceptors.response.use(undefined, (error) => {
// @ts-ignore
responseInterceptorsCatch(this.axiosInstance, error);
});
}
/**
......
import { AxiosError, AxiosInstance } from 'axios';
/**
* 请求重试机制
*/
export class AxiosRetry {
/**
* 重试
*/
retry(AxiosInstance: AxiosInstance, error: AxiosError) {
// @ts-ignore
const { config } = error.response;
const { waitTime, count } = config?.requestOptions?.retryRequest;
config.__retryCount = config.__retryCount || 0;
if (config.__retryCount >= count) {
return Promise.reject(error);
}
config.__retryCount += 1;
return this.delay(waitTime).then(() => AxiosInstance(config));
}
/**
* 延迟
*/
private delay(waitTime: number) {
return new Promise((resolve) => setTimeout(resolve, waitTime));
}
}
......@@ -48,5 +48,5 @@ export abstract class AxiosTransform {
/**
* @description: 请求之后的拦截器错误处理
*/
responseInterceptorsCatch?: (error: Error) => void;
responseInterceptorsCatch?: (axiosInstance: AxiosResponse, error: Error) => void;
}
......@@ -17,6 +17,7 @@ import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
import { useI18n } from '/@/hooks/web/useI18n';
import { joinTimestamp, formatRequestDate } from './helper';
import { useUserStoreWithOut } from '/@/store/modules/user';
import { AxiosRetry } from '/@/utils/http/axios/axiosRetry';
const globSetting = useGlobSetting();
const urlPrefix = globSetting.urlPrefix;
......@@ -158,7 +159,7 @@ const transform: AxiosTransform = {
/**
* @description: 响应错误处理
*/
responseInterceptorsCatch: (error: any) => {
responseInterceptorsCatch: (axiosInstance: AxiosResponse, error: any) => {
const { t } = useI18n();
const errorLogStore = useErrorLogStoreWithOut();
errorLogStore.addAjaxErrorInfo(error);
......@@ -189,6 +190,14 @@ const transform: AxiosTransform = {
}
checkStatus(error?.response?.status, msg, errorMessageMode);
// 添加自动重试机制 保险起见 只针对GET请求
const retryRequest = new AxiosRetry();
const { isOpenRetry } = config.requestOptions.retryRequest;
config.method?.toUpperCase() === RequestEnum.GET &&
isOpenRetry &&
// @ts-ignore
retryRequest.retry(axiosInstance, error);
return Promise.reject(error);
},
};
......@@ -234,6 +243,11 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
ignoreCancelToken: true,
// 是否携带token
withToken: true,
retryRequest: {
isOpenRetry: true,
count: 5,
waitTime: 100,
},
},
},
opt || {},
......
<template>
<div class="request-box">
<a-button @click="handleClick" color="primary"> 点击会重新发起请求5次 </a-button>
<p>打开浏览器的network面板,可以看到发出了六次请求</p>
</div>
</template>
<script lang="ts" setup>
import { testRetry } from '/@/api/sys/user';
// @ts-ignore
const handleClick = async () => {
await testRetry();
};
</script>
<style lang="less">
.request-box {
margin: 50px;
}
p {
margin-top: 10px;
}
</style>
......@@ -23,8 +23,15 @@ export interface RequestOptions {
ignoreCancelToken?: boolean;
// Whether to send token in header
withToken?: boolean;
// 请求重试机制
retryRequest?: RetryRequest;
}
export interface RetryRequest {
isOpenRetry: boolean;
count: number;
waitTime: number;
}
export interface Result<T = any> {
code: number;
type: 'success' | 'error' | 'warning';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册