mirror of
https://github.com/vbenjs/gf-vben-admin.git
synced 2025-01-23 03:40:19 +08:00
feat: add request retry (#1553)
This commit is contained in:
parent
78535bdd86
commit
136cbb1e3b
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
28
src/utils/http/axios/axiosRetry.ts
Normal file
28
src/utils/http/axios/axiosRetry.ts
Normal file
@ -0,0 +1,28 @@
|
||||
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 || {},
|
||||
|
23
src/views/demo/feat/request-demo/index.vue
Normal file
23
src/views/demo/feat/request-demo/index.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<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>
|
7
types/axios.d.ts
vendored
7
types/axios.d.ts
vendored
@ -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';
|
||||
|
Loading…
Reference in New Issue
Block a user