| | |
| | | import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios'; |
| | | |
| | | import type { AxiosRequestConfig, AxiosInstance, AxiosResponse, AxiosError } from 'axios'; |
| | | import type { RequestOptions, Result, UploadFileParams } from '/#/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 } from 'lodash-es'; |
| | | |
| | | import { RequestOptions, CreateAxiosOptions, Result } from './types'; |
| | | import { ContentTypeEnum } from '/@/enums/httpEnum'; |
| | | import { RequestEnum } from '/@/enums/httpEnum'; |
| | | |
| | | export * from './axiosTransform'; |
| | | |
| | | /** |
| | | * @description: axios模块 |
| | | * @description: axios module |
| | | */ |
| | | export class VAxios { |
| | | private axiosInstance: AxiosInstance; |
| | | private options: CreateAxiosOptions; |
| | | private readonly options: CreateAxiosOptions; |
| | | |
| | | constructor(options: CreateAxiosOptions) { |
| | | this.options = options; |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description: 创建axios实例 |
| | | * @description: Create axios instance |
| | | */ |
| | | private createAxios(config: CreateAxiosOptions): void { |
| | | this.axiosInstance = axios.create(config); |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description: 重新配置axios |
| | | * @description: Reconfigure axios |
| | | */ |
| | | configAxios(config: CreateAxiosOptions) { |
| | | if (!this.axiosInstance) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description: 设置通用header |
| | | * @description: Set general header |
| | | */ |
| | | setHeader(headers: any): void { |
| | | if (!this.axiosInstance) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description: 拦截器配置 |
| | | * @description: Interceptor configuration |
| | | */ |
| | | private setupInterceptors() { |
| | | const transform = this.getTransform(); |
| | |
| | | |
| | | const axiosCanceler = new AxiosCanceler(); |
| | | |
| | | // 请求拦截器配置处理 |
| | | // Request interceptor configuration processing |
| | | this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => { |
| | | const { headers: { ignoreCancelToken } = { ignoreCancelToken: false } } = config; |
| | | !ignoreCancelToken && axiosCanceler.addPending(config); |
| | | // If cancel repeat request is turned on, then cancel repeat request is prohibited |
| | | // @ts-ignore |
| | | const { ignoreCancelToken } = config.requestOptions; |
| | | const ignoreCancel = |
| | | ignoreCancelToken !== undefined |
| | | ? ignoreCancelToken |
| | | : this.options.requestOptions?.ignoreCancelToken; |
| | | |
| | | !ignoreCancel && axiosCanceler.addPending(config); |
| | | if (requestInterceptors && isFunction(requestInterceptors)) { |
| | | config = requestInterceptors(config); |
| | | config = requestInterceptors(config, this.options); |
| | | } |
| | | return config; |
| | | }, undefined); |
| | | |
| | | // 请求拦截器错误捕获 |
| | | // Request interceptor error capture |
| | | requestInterceptorsCatch && |
| | | isFunction(requestInterceptorsCatch) && |
| | | this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch); |
| | | |
| | | // 响应结果拦截器处理 |
| | | // Response result interceptor processing |
| | | this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => { |
| | | res && axiosCanceler.removePending(res.config); |
| | | if (responseInterceptors && isFunction(responseInterceptors)) { |
| | |
| | | return res; |
| | | }, undefined); |
| | | |
| | | // 响应结果拦截器错误捕获 |
| | | // Response result interceptor error capture |
| | | responseInterceptorsCatch && |
| | | isFunction(responseInterceptorsCatch) && |
| | | this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch); |
| | | this.axiosInstance.interceptors.response.use(undefined, (error) => { |
| | | // @ts-ignore |
| | | responseInterceptorsCatch(this.axiosInstance, error); |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * @description: 文件上传 |
| | | * @description: File Upload |
| | | */ |
| | | uploadFiles(config: AxiosRequestConfig, params: File[]) { |
| | | const formData = new FormData(); |
| | | uploadFile<T = any>(config: AxiosRequestConfig, params: UploadFileParams) { |
| | | const formData = new window.FormData(); |
| | | const customFilename = params.name || 'file'; |
| | | |
| | | Object.keys(params).forEach((key) => { |
| | | formData.append(key, params[key as any]); |
| | | }); |
| | | if (params.filename) { |
| | | formData.append(customFilename, params.file, params.filename); |
| | | } else { |
| | | formData.append(customFilename, params.file); |
| | | } |
| | | |
| | | return this.request({ |
| | | 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, |
| | | // @ts-ignore |
| | | ignoreCancelToken: true, |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * @description: 请求方法 |
| | | */ |
| | | // support form-data |
| | | supportFormData(config: AxiosRequestConfig) { |
| | | const headers = config.headers || this.options.headers; |
| | | const contentType = headers?.['Content-Type'] || headers?.['content-type']; |
| | | |
| | | if ( |
| | | contentType !== ContentTypeEnum.FORM_URLENCODED || |
| | | !Reflect.has(config, 'data') || |
| | | config.method?.toUpperCase() === RequestEnum.GET |
| | | ) { |
| | | return config; |
| | | } |
| | | |
| | | return { |
| | | ...config, |
| | | data: qs.stringify(config.data, { arrayFormat: 'brackets' }), |
| | | }; |
| | | } |
| | | |
| | | 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: AxiosRequestConfig = cloneDeep(config); |
| | | let conf: CreateAxiosOptions = cloneDeep(config); |
| | | const transform = this.getTransform(); |
| | | |
| | | const { requestOptions } = this.options; |
| | | |
| | | const opt: RequestOptions = Object.assign({}, requestOptions, options); |
| | | |
| | | const { beforeRequestHook, requestCatch, transformRequestData } = transform || {}; |
| | | const { beforeRequestHook, requestCatchHook, transformRequestHook } = transform || {}; |
| | | if (beforeRequestHook && isFunction(beforeRequestHook)) { |
| | | conf = beforeRequestHook(conf, opt); |
| | | } |
| | | conf.requestOptions = opt; |
| | | |
| | | conf = this.supportFormData(conf); |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | this.axiosInstance |
| | | .request<any, AxiosResponse<Result>>(conf) |
| | | .then((res: AxiosResponse<Result>) => { |
| | | if (transformRequestData && isFunction(transformRequestData)) { |
| | | const ret = transformRequestData(res, opt); |
| | | ret !== undefined ? resolve(ret) : reject(new Error('request error!')); |
| | | 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>); |
| | | resolve(res as unknown as Promise<T>); |
| | | }) |
| | | .catch((e: Error) => { |
| | | if (requestCatch && isFunction(requestCatch)) { |
| | | reject(requestCatch(e)); |
| | | .catch((e: Error | AxiosError) => { |
| | | if (requestCatchHook && isFunction(requestCatchHook)) { |
| | | reject(requestCatchHook(e, opt)); |
| | | return; |
| | | } |
| | | if (axios.isAxiosError(e)) { |
| | | // rewrite error message from axios in here |
| | | } |
| | | reject(e); |
| | | }); |
| | | }); |