永旺用户心声
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

104 lines
3.3 KiB

import axios, { type AxiosResponse, AxiosInstance, InternalAxiosRequestConfig } from 'axios'
import { addPrefixByRecursive } from '@/utils/utils'
import type { RequestConfig, RequestInterceptors, CreateRequestConfig } from './types'
export default class Request {
// axios 实例
instance: AxiosInstance
// 拦截器对象
interceptorsObj?: RequestInterceptors<AxiosResponse>
// * 存放取消请求控制器Map
abortControllerMap: Map<string, AbortController>
constructor(config: CreateRequestConfig) {
this.instance = axios.create(config)
//取消请求控制器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<T>(config: RequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
if (config.interceptors?.requestInterceptors) {
config = config.interceptors.requestInterceptors(config as any)
}
this.instance
.request<any, T>(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()
}
/**
* 取消指定的请求
* @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: {
responseInterceptors(config) {
const isJson = /.json$/.test(config.config.url as string)
isJson && addPrefixByRecursive(config.data.data)
return config
}
}
})
export type Response<T> = {
msg: string
data: T
code: number
}
export const request = <T = any>(config: RequestConfig<Response<T>>) => _request.request(config)
export const cancelRequest = (url: string | string[]) => _request.cancelRequest(url)
export const cancelAllRequest = () => _request.cancelAllRequest()