import axios from 'axios' import type { AxiosResponse, AxiosInstance, InternalAxiosRequestConfig } from 'axios' import { addPrefixByRecursive } from '@/utils/utils' import type { RequestConfig, RequestInterceptors, CreateRequestConfig } from './types' import { useRootStore } from '@/stores/root' import axiosRetry from 'axios-retry' export default class Request { // axios 实例 instance: AxiosInstance // 拦截器对象 interceptorsObj?: RequestInterceptors // * 存放取消请求控制器Map abortControllerMap: Map constructor(config: CreateRequestConfig) { this.instance = axios.create(config) axiosRetry(this.instance, { retries: 3 }) //取消请求控制器Map this.abortControllerMap = new Map() this.interceptorsObj = config.interceptors // 拦截器执行顺序 接口请求 -> 实例请求 -> 全局请求 -> 实例响应 -> 全局响应 -> 接口响应 this.instance.interceptors.request.use( (res: InternalAxiosRequestConfig) => { const controller = new AbortController() const url = res.url || '' res.signal = controller.signal this.abortControllerMap.set(url, controller) return res }, (err: any) => err ) // 使用实例拦截器 this.instance.interceptors.request.use(this.interceptorsObj?.requestInterceptors, this.interceptorsObj?.requestInterceptorsCatch) this.instance.interceptors.response.use(this.interceptorsObj?.responseInterceptors, this.interceptorsObj?.responseInterceptorsCatch) this.instance.interceptors.response.use( (res: AxiosResponse) => { const url = res.config.url || '' this.abortControllerMap.delete(url) return res.data }, (err: any) => err ) } request(config: RequestConfig): Promise { return new Promise((resolve, reject) => { if (config.interceptors?.requestInterceptors) { config = config.interceptors.requestInterceptors(config as any) } this.instance .request(config) .then(res => { // 如果为单个响应设置拦截器,使用单个响应的拦截器 if (config.interceptors?.responseInterceptors) { res = config.interceptors.responseInterceptors(res) } resolve(res) }) .catch((err: any) => { reject(err) }) }) } //取消全部请求 cancelAllRequest() { for (const [, controller] of this.abortControllerMap) { controller.abort() } this.abortControllerMap.clear() } /** * @description 取消指定的请求 * @param url 待取消的请求URL */ cancelRequest(url: string | string[]) { const urlList = Array.isArray(url) ? url : [url] for (const _url of urlList) { this.abortControllerMap.get(_url)?.abort() this.abortControllerMap.delete(_url) } } } const _request = new Request({ timeout: 10000, timeoutErrorMessage: '网络超时', interceptors: { requestInterceptors(config) { if (/\.json$/i.test(config.url as string)) { config.params = config.params || {} config.params.t = Date.now() } return config }, responseInterceptors(config) { const isJson = /.json$/.test(config.config.url as string) isJson && addPrefixByRecursive(config.data.data) return config } } }) export type Response = { msg: string data: T code: number } export function getPrefixUrl() { const store = useRootStore() return store.config } export const request = (config: RequestConfig>) => _request.request(config) export const cancelRequest = (url: string | string[]) => _request.cancelRequest(url) export const cancelAllRequest = () => _request.cancelAllRequest()