auth-web/src/api/service/mockRequest.ts

153 lines
4.9 KiB
TypeScript
Raw Normal View History

import Axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios';
import type { PureHttpError, PureHttpRequestConfig, PureHttpResponse, RequestMethods } from './types';
import NProgress from '../../utils/progress';
import { formatToken, getToken } from '@/utils/auth';
import { useUserStoreHook } from '@/store/system/user';
import { defaultMockConfig } from '@/api/service/config';
2024-09-26 09:38:02 +08:00
class PureHttp {
/** `token`过期后,暂存待执行的请求 */
private static requests = [];
/** 防止重复刷新`token` */
private static isRefreshing = false;
/** 初始化配置对象 */
private static initConfig: PureHttpRequestConfig = {};
/** 保存当前`Axios`实例对象 */
private static axiosInstance: AxiosInstance = Axios.create(defaultMockConfig);
2024-09-26 09:38:02 +08:00
constructor() {
this.httpInterceptorsRequest();
this.httpInterceptorsResponse();
}
2024-09-26 09:38:02 +08:00
/** 重连原始请求 */
private static retryOriginalRequest(config: PureHttpRequestConfig) {
return new Promise(resolve => {
PureHttp.requests.push((token: string) => {
config.headers['token'] = formatToken(token);
resolve(config);
});
});
}
2024-09-26 09:38:02 +08:00
/** 通用请求工具函数 */
public request<T>(method: RequestMethods, url: string, param?: AxiosRequestConfig, axiosConfig?: PureHttpRequestConfig): Promise<T> {
const config = {
method,
url,
...param,
...axiosConfig,
} as PureHttpRequestConfig;
2024-09-26 09:38:02 +08:00
// 单独处理自定义请求/响应回调
return new Promise((resolve, reject) => {
PureHttp.axiosInstance
.request(config)
.then((response: undefined) => {
resolve(response);
})
.catch(error => {
reject(error);
});
});
}
2024-09-26 09:38:02 +08:00
/** 单独抽离的`post`工具函数 */
public post<T, P>(url: string, params?: AxiosRequestConfig<P>, config?: PureHttpRequestConfig): Promise<T> {
return this.request<T>('post', url, params, config);
}
2024-09-26 09:38:02 +08:00
/** 单独抽离的`get`工具函数 */
public get<T, P>(url: string, params?: AxiosRequestConfig<P>, config?: PureHttpRequestConfig): Promise<T> {
return this.request<T>('get', url, params, config);
}
2024-09-26 09:38:02 +08:00
/** 请求拦截 */
private httpInterceptorsRequest(): void {
PureHttp.axiosInstance.interceptors.request.use(
async (config: PureHttpRequestConfig): Promise<any> => {
// 开启进度条动画
NProgress.start();
// 优先判断post/get等方法是否传入回调否则执行初始化设置等回调
if (typeof config.beforeRequestCallback === 'function') {
config.beforeRequestCallback(config);
return config;
}
if (PureHttp.initConfig.beforeRequestCallback) {
PureHttp.initConfig.beforeRequestCallback(config);
return config;
}
/** 请求白名单,放置一些不需要`token`的接口(通过设置请求白名单,防止`token`过期后再请求造成的死循环问题) */
const whiteList = ['/refresh-token', '/login'];
return whiteList.some(url => config.url.endsWith(url))
? config
: new Promise(resolve => {
const data: any = getToken();
if (data) {
const now = new Date().getTime();
const expired = parseInt(data.expires) - now <= 0;
if (expired) {
if (!PureHttp.isRefreshing) {
PureHttp.isRefreshing = true;
// token过期刷新
useUserStoreHook()
.handRefreshToken({ refreshToken: data.refreshToken })
.then((res: any) => {
const token = res.data.accessToken;
config.headers['Authorization'] = formatToken(token);
PureHttp.requests.forEach(cb => cb(token));
PureHttp.requests = [];
})
.finally(() => {
PureHttp.isRefreshing = false;
});
}
resolve(PureHttp.retryOriginalRequest(config));
} else {
config.headers['Authorization'] = formatToken(data.accessToken);
resolve(config);
}
} else {
resolve(config);
}
});
},
error => {
return Promise.reject(error);
},
);
}
2024-09-26 09:38:02 +08:00
/** 响应拦截 */
private httpInterceptorsResponse(): void {
const instance = PureHttp.axiosInstance;
instance.interceptors.response.use(
(response: PureHttpResponse) => {
const $config = response.config;
// 关闭进度条动画
NProgress.done();
// 优先判断post/get等方法是否传入回调否则执行初始化设置等回调
if (typeof $config.beforeResponseCallback === 'function') {
$config.beforeResponseCallback(response);
return response.data;
}
if (PureHttp.initConfig.beforeResponseCallback) {
PureHttp.initConfig.beforeResponseCallback(response);
return response.data;
}
return response.data;
},
(error: PureHttpError) => {
const $error = error;
$error.isCancelRequest = Axios.isCancel($error);
// 关闭进度条动画
NProgress.done();
// 所有的响应异常 区分来源为取消请求/非取消请求
return Promise.reject($error);
},
);
}
2024-09-26 09:38:02 +08:00
}
export const http = new PureHttp();