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.
225 lines
6.8 KiB
225 lines
6.8 KiB
/** |
|
* @program: kicc-ui |
|
* @description: 扩展axios模块 |
|
* @author: entfrm开发团队-王翔 |
|
* @create: 2022/4/7 |
|
*/ |
|
|
|
import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios'; |
|
import type { RequestOptions, R, UploadFileParams } from '../../../../types/axios'; |
|
import type { CreateAxiosOptions } from './axiosTransform'; |
|
import axios from 'axios'; |
|
import qs from 'qs'; |
|
import { AxiosCanceler } from './axiosCancel'; |
|
import { isFunction } from '/@/utils/is'; |
|
import { cloneDeep, omit } from 'lodash-es'; |
|
import { ContentTypeEnum } from '/@/enums/httpEnum'; |
|
import { RequestEnum } from '/@/enums/httpEnum'; |
|
|
|
export * from './axiosTransform'; |
|
|
|
export class VAxios { |
|
private axiosInstance: AxiosInstance; |
|
private readonly options: CreateAxiosOptions; |
|
|
|
constructor(options: CreateAxiosOptions) { |
|
this.options = options; |
|
this.axiosInstance = axios.create(options); |
|
this.setupInterceptors(); |
|
} |
|
|
|
/** 创建 axios 实例 */ |
|
private createAxios(config: CreateAxiosOptions): void { |
|
this.axiosInstance = axios.create(config); |
|
} |
|
|
|
private getTransform() { |
|
const { transform } = this.options; |
|
return transform; |
|
} |
|
|
|
getAxios(): AxiosInstance { |
|
return this.axiosInstance; |
|
} |
|
|
|
/** 值得重新配置 */ |
|
configAxios(config: CreateAxiosOptions) { |
|
if (!this.axiosInstance) { |
|
return; |
|
} |
|
this.createAxios(config); |
|
} |
|
|
|
/** 设置headers请求头 */ |
|
setHeader(headers: any): void { |
|
if (!this.axiosInstance) { |
|
return; |
|
} |
|
Object.assign(this.axiosInstance.defaults.headers, headers); |
|
} |
|
|
|
/** 拦截器配置 */ |
|
private setupInterceptors() { |
|
const transform = this.getTransform(); |
|
if (!transform) { |
|
return; |
|
} |
|
const { |
|
requestInterceptors, |
|
requestInterceptorsCatch, |
|
responseInterceptors, |
|
responseInterceptorsCatch, |
|
} = transform; |
|
|
|
const axiosCanceler = new AxiosCanceler(); |
|
|
|
// 请求拦截器配置处理 |
|
this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => { |
|
// 如果开启了取消重复请求,则禁止取消重复请求 |
|
const { |
|
headers: { ignoreCancelToken }, |
|
} = config; |
|
|
|
const ignoreCancel = |
|
ignoreCancelToken !== undefined |
|
? ignoreCancelToken |
|
: this.options.requestOptions?.ignoreCancelToken; |
|
|
|
!ignoreCancel && axiosCanceler.addPending(config); |
|
if (requestInterceptors && isFunction(requestInterceptors)) { |
|
config = requestInterceptors(config, this.options); |
|
} |
|
return config; |
|
}, undefined); |
|
|
|
// 请求拦截器错误捕获 |
|
requestInterceptorsCatch && |
|
isFunction(requestInterceptorsCatch) && |
|
this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch); |
|
|
|
// 响应结果拦截器处理 |
|
this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => { |
|
res && axiosCanceler.removePending(res.config); |
|
if (responseInterceptors && isFunction(responseInterceptors)) { |
|
res = responseInterceptors(res); |
|
} |
|
return res; |
|
}, undefined); |
|
|
|
// 响应结果拦截器错误捕获 |
|
responseInterceptorsCatch && |
|
isFunction(responseInterceptorsCatch) && |
|
this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch); |
|
} |
|
|
|
/** 上传文件 */ |
|
uploadFile<T = any>(config: AxiosRequestConfig, params: UploadFileParams) { |
|
const formData = new window.FormData(); |
|
const customFilename = params.name || 'file'; |
|
|
|
if (params.filename) { |
|
formData.append(customFilename, params.file, params.filename); |
|
} else { |
|
formData.append(customFilename, params.file); |
|
} |
|
|
|
if (params.data) { |
|
Object.keys(params.data).forEach((key) => { |
|
const value = params.data![key]; |
|
if (Array.isArray(value)) { |
|
value.forEach((item) => { |
|
formData.append(`${key}[]`, item); |
|
}); |
|
return; |
|
} |
|
|
|
formData.append(key, params.data![key]); |
|
}); |
|
} |
|
|
|
return this.axiosInstance.request<T>({ |
|
...config, |
|
method: 'POST', |
|
data: formData, |
|
headers: { |
|
'Content-type': ContentTypeEnum.FORM_DATA, |
|
ignoreCancelToken: true, |
|
}, |
|
}); |
|
} |
|
|
|
/** 转换配置数据格式 */ |
|
transformConfigFormat(config: AxiosRequestConfig) { |
|
const headers = config.headers || this.options.headers; |
|
const contentType = headers?.['Content-Type'] || headers?.['content-type']; |
|
const arrayFormat = headers.arrayFormat || 'indices'; |
|
|
|
if (config.method?.toUpperCase() === RequestEnum.POST && contentType === ContentTypeEnum.FORM_URLENCODED) { |
|
// post请求参数处理 |
|
config.data = qs.stringify(config.data, { allowDots: true, arrayFormat: arrayFormat }); |
|
} else if (config.method?.toUpperCase() === RequestEnum.GET) { |
|
// get请求参数处理 |
|
config.params = qs.stringify(config.params, { allowDots: true, arrayFormat: arrayFormat }); |
|
config.params = qs.parse(config.params); |
|
} |
|
|
|
return config; |
|
} |
|
|
|
get<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> { |
|
return this.request({ ...config, method: 'GET' }, options); |
|
} |
|
|
|
post<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> { |
|
return this.request({ ...config, method: 'POST' }, options); |
|
} |
|
|
|
put<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> { |
|
return this.request({ ...config, method: 'PUT' }, options); |
|
} |
|
|
|
delete<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> { |
|
return this.request({ ...config, method: 'DELETE' }, options); |
|
} |
|
|
|
request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> { |
|
let conf: CreateAxiosOptions = cloneDeep(config); |
|
const transform = this.getTransform(); |
|
|
|
const { requestOptions } = this.options; |
|
|
|
const opt: RequestOptions = Object.assign({}, requestOptions, options); |
|
|
|
const { beforeRequestHook, requestCatchHook, transformRequestHook } = transform || {}; |
|
if (beforeRequestHook && isFunction(beforeRequestHook)) { |
|
conf = beforeRequestHook(conf, opt); |
|
} |
|
conf.requestOptions = opt; |
|
|
|
conf = this.transformConfigFormat(conf); |
|
|
|
return new Promise((resolve, reject) => { |
|
this.axiosInstance |
|
.request<any, AxiosResponse<R>>(conf) |
|
.then((res: AxiosResponse<R>) => { |
|
if (transformRequestHook && isFunction(transformRequestHook)) { |
|
try { |
|
const ret = transformRequestHook(res, opt); |
|
resolve(ret); |
|
} catch (err) { |
|
reject(err || new Error('request error!')); |
|
} |
|
return; |
|
} |
|
resolve(res as unknown as Promise<T>); |
|
}) |
|
.catch((e: Error) => { |
|
if (requestCatchHook && isFunction(requestCatchHook)) { |
|
reject(requestCatchHook(e, opt)); |
|
return; |
|
} |
|
reject(e); |
|
}); |
|
}); |
|
} |
|
}
|
|
|