|
@@ -0,0 +1,89 @@
|
|
|
|
+import axios, { AxiosError, type AxiosInstance, type AxiosRequestConfig, type AxiosResponse, type InternalAxiosRequestConfig } from 'axios'
|
|
|
|
+import { ResultEnum } from '@/enums/HttpEnum'
|
|
|
|
+import { defaultRequestInterceptors, defaultResponseInterceptors } from './config'
|
|
|
|
+interface RequestInterceptors<T> {
|
|
|
|
+ // 请求拦截
|
|
|
|
+ requestInterceptors?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig
|
|
|
|
+ requestInterceptorsCatch?: (err: any) => any
|
|
|
|
+ // 响应拦截
|
|
|
|
+ responseInterceptors?: (config: T) => T
|
|
|
|
+ responseInterceptorsCatch?: (err: any) => any
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+interface RequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
|
|
|
|
+ interceptors?: RequestInterceptors<T>
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export const BASE_URL = import.meta.env.VITE_USE_MOCK ? import.meta.env.VITE_MOCK_API_PREFIX_PATH : import.meta.env.VITE_API_PREFIX_PATH
|
|
|
|
+
|
|
|
|
+const abortControllerMap: Map<string, AbortController> = new Map()
|
|
|
|
+
|
|
|
|
+const config = {
|
|
|
|
+ // 默认地址请求地址,可在 .env.** 文件中修改
|
|
|
|
+ baseURL: BASE_URL as string,
|
|
|
|
+ // 设置超时时间
|
|
|
|
+ timeout: ResultEnum.TIMEOUT as number,
|
|
|
|
+ // 跨域时候允许携带凭证
|
|
|
|
+ withCredentials: true
|
|
|
|
+}
|
|
|
|
+// instantiation
|
|
|
|
+const axiosInstance: AxiosInstance = axios.create(config)
|
|
|
|
+
|
|
|
|
+axiosInstance.interceptors.request.use((res: InternalAxiosRequestConfig) => {
|
|
|
|
+ const controller = new AbortController()
|
|
|
|
+ const url = res.url || ''
|
|
|
|
+ res.signal = controller.signal
|
|
|
|
+ abortControllerMap.set(url, controller)
|
|
|
|
+ return res
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+axiosInstance.interceptors.response.use(
|
|
|
|
+ (res: AxiosResponse) => {
|
|
|
|
+ const url = res.config.url || ''
|
|
|
|
+ abortControllerMap.delete(url)
|
|
|
|
+ return res
|
|
|
|
+ },
|
|
|
|
+ (error: AxiosError) => {
|
|
|
|
+ console.log('err: ' + error)
|
|
|
|
+ return Promise.reject(error)
|
|
|
|
+ }
|
|
|
|
+)
|
|
|
|
+// 默认请求/响应 处理
|
|
|
|
+axiosInstance.interceptors.request.use(defaultRequestInterceptors)
|
|
|
|
+axiosInstance.interceptors.response.use(defaultResponseInterceptors)
|
|
|
|
+
|
|
|
|
+const service = {
|
|
|
|
+ request: (config: RequestConfig) => {
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
+ if (config.interceptors?.requestInterceptors) {
|
|
|
|
+ config = config.interceptors.requestInterceptors(config as any)
|
|
|
|
+ }
|
|
|
|
+ axiosInstance
|
|
|
|
+ .request(config)
|
|
|
|
+ .then(res => {
|
|
|
|
+ resolve(res)
|
|
|
|
+ })
|
|
|
|
+ .catch((err: any) => {
|
|
|
|
+ reject(err)
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 取消请求
|
|
|
|
+ cancelRequest: (url: string | string[]) => {
|
|
|
|
+ const urlList = Array.isArray(url) ? url : [url]
|
|
|
|
+ for (const _url of urlList) {
|
|
|
|
+ abortControllerMap.get(_url)?.abort()
|
|
|
|
+ abortControllerMap.delete(_url)
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 取消所有请求
|
|
|
|
+ cancelAllRequest() {
|
|
|
|
+ for (const [_, controller] of abortControllerMap) {
|
|
|
|
+ controller.abort()
|
|
|
|
+ }
|
|
|
|
+ abortControllerMap.clear()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+export default service
|