Skip to content

Commit 5ae17e6

Browse files
committed
fix(projects): fix refresh token when meet multi requests
1 parent 4909291 commit 5ae17e6

File tree

4 files changed

+37
-33
lines changed

4 files changed

+37
-33
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ VITE_SERVICE_LOGOUT_CODES=8888,8889
3636
VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
3737

3838
# token expired codes of backend service, when the code is received, it will refresh the token and resend the request
39-
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998
39+
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998,3333
4040

4141
# when the route mode is static, the defined super role
4242
VITE_STATIC_SUPER_ROLE=R_SUPER

src/service/request/index.ts

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useAuthStore } from '@/store/modules/auth';
44
import { localStg } from '@/utils/storage';
55
import { getServiceBaseURL } from '@/utils/service';
66
import { $t } from '@/locales';
7-
import { handleRefreshToken, showErrorMsg } from './shared';
7+
import { getAuthorization, handleExpiredRequest, showErrorMsg } from './shared';
88
import type { RequestInstanceState } from './type';
99

1010
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
@@ -19,12 +19,8 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
1919
},
2020
{
2121
async onRequest(config) {
22-
const { headers } = config;
23-
24-
// set token
25-
const token = localStg.get('token');
26-
const Authorization = token ? `Bearer ${token}` : null;
27-
Object.assign(headers, { Authorization });
22+
const Authorization = getAuthorization();
23+
Object.assign(config.headers, { Authorization });
2824

2925
return config;
3026
},
@@ -82,15 +78,13 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
8278
// when the backend response code is in `expiredTokenCodes`, it means the token is expired, and refresh token
8379
// the api `refreshToken` can not return error code in `expiredTokenCodes`, otherwise it will be a dead loop, should return `logoutCodes` or `modalLogoutCodes`
8480
const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || [];
85-
if (expiredTokenCodes.includes(responseCode) && !request.state.isRefreshingToken) {
86-
request.state.isRefreshingToken = true;
87-
88-
const refreshConfig = await handleRefreshToken(response.config);
89-
90-
request.state.isRefreshingToken = false;
81+
if (expiredTokenCodes.includes(responseCode)) {
82+
const success = await handleExpiredRequest(request.state);
83+
if (success) {
84+
const Authorization = getAuthorization();
85+
Object.assign(response.config.headers, { Authorization });
9186

92-
if (refreshConfig) {
93-
return instance.request(refreshConfig) as Promise<AxiosResponse>;
87+
return instance.request(response.config) as Promise<AxiosResponse>;
9488
}
9589
}
9690

src/service/request/shared.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,44 @@
1-
import type { AxiosRequestConfig } from 'axios';
21
import { useAuthStore } from '@/store/modules/auth';
32
import { localStg } from '@/utils/storage';
43
import { fetchRefreshToken } from '../api';
54
import type { RequestInstanceState } from './type';
65

7-
/**
8-
* refresh token
9-
*
10-
* @param axiosConfig - request config when the token is expired
11-
*/
12-
export async function handleRefreshToken(axiosConfig: AxiosRequestConfig) {
6+
export function getAuthorization() {
7+
const token = localStg.get('token');
8+
const Authorization = token ? `Bearer ${token}` : null;
9+
10+
return Authorization;
11+
}
12+
13+
/** refresh token */
14+
async function handleRefreshToken() {
1315
const { resetStore } = useAuthStore();
1416

15-
const refreshToken = localStg.get('refreshToken') || '';
16-
const { error, data } = await fetchRefreshToken(refreshToken);
17+
const rToken = localStg.get('refreshToken') || '';
18+
const { error, data } = await fetchRefreshToken(rToken);
1719
if (!error) {
1820
localStg.set('token', data.token);
1921
localStg.set('refreshToken', data.refreshToken);
22+
return true;
23+
}
2024

21-
const config = { ...axiosConfig };
22-
if (config.headers) {
23-
config.headers.Authorization = data.token;
24-
}
25+
resetStore();
2526

26-
return config;
27+
return false;
28+
}
29+
30+
export async function handleExpiredRequest(state: RequestInstanceState) {
31+
if (!state.refreshTokenFn) {
32+
state.refreshTokenFn = handleRefreshToken();
2733
}
2834

29-
resetStore();
35+
const success = await state.refreshTokenFn;
36+
37+
setTimeout(() => {
38+
state.refreshTokenFn = null;
39+
}, 1000);
3040

31-
return null;
41+
return success;
3242
}
3343

3444
export function showErrorMsg(state: RequestInstanceState, message: string) {

src/service/request/type.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export interface RequestInstanceState {
22
/** whether the request is refreshing token */
3-
isRefreshingToken: boolean;
3+
refreshTokenFn: Promise<boolean> | null;
44
/** the request error message stack */
55
errMsgStack: string[];
66
}

0 commit comments

Comments
 (0)