Skip to content

Commit

Permalink
feat: add request retry (vbenjs#1553)
Browse files Browse the repository at this point in the history
  • Loading branch information
MssText authored Mar 18, 2022
1 parent 78535bd commit 136cbb1
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 3 deletions.
8 changes: 8 additions & 0 deletions mock/sys/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
14 changes: 14 additions & 0 deletions src/api/sys/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ enum Api {
Logout = '/logout',
GetUserInfo = '/getUserInfo',
GetPermCode = '/getPermCode',
TestRetry = '/testRetry',
}

/**
Expand Down Expand Up @@ -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,
},
},
);
}
1 change: 1 addition & 0 deletions src/locales/lang/en/routes/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 1 addition & 0 deletions src/locales/lang/zh-CN/routes/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export default {
ws: 'websocket测试',
breadcrumb: '面包屑导航',
breadcrumbFlat: '平级模式',
requestDemo: '测试请求重试',
breadcrumbFlatDetail: '平级详情',
breadcrumbChildren: '层级模式',
breadcrumbChildrenDetail: '层级详情',
Expand Down
9 changes: 9 additions & 0 deletions src/router/routes/modules/demo/feat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
5 changes: 4 additions & 1 deletion src/utils/http/axios/Axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
}

/**
Expand Down
28 changes: 28 additions & 0 deletions src/utils/http/axios/axiosRetry.ts
Original file line number Diff line number Diff line change
@@ -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));
}
}
2 changes: 1 addition & 1 deletion src/utils/http/axios/axiosTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ export abstract class AxiosTransform {
/**
* @description: 请求之后的拦截器错误处理
*/
responseInterceptorsCatch?: (error: Error) => void;
responseInterceptorsCatch?: (axiosInstance: AxiosResponse, error: Error) => void;
}
16 changes: 15 additions & 1 deletion src/utils/http/axios/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
},
};
Expand Down Expand Up @@ -234,6 +243,11 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
ignoreCancelToken: true,
// 是否携带token
withToken: true,
retryRequest: {
isOpenRetry: true,
count: 5,
waitTime: 100,
},
},
},
opt || {},
Expand Down
23 changes: 23 additions & 0 deletions src/views/demo/feat/request-demo/index.vue
Original file line number Diff line number Diff line change
@@ -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 changes: 7 additions & 0 deletions types/axios.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down

0 comments on commit 136cbb1

Please sign in to comment.