import { cloneDeep } from 'lodash-es'; import axios from 'axios'; import { ContentTypeEnum } from '../../enums/httpEnum'; import { isFunction } from '../../method/is'; import type { RequestOptions, Result, UploadFileParams } from '../../types/axios'; import { AxiosCanceler } from './axiosCancel'; import type { CreateAxiosOptions } from './axiosTransform'; import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; export * from './axiosTransform'; /** * @description: 封装axios请求,返回重新封装的数据格式 */ export class CordysAxios { public axiosInstance: AxiosInstance; private readonly options: CreateAxiosOptions; constructor(options: CreateAxiosOptions) { this.options = options; this.axiosInstance = axios.create(options); this.setupInterceptors(); } private getTransform() { const { transform } = this.options; return transform; } /** * @description: 拦截器配置 */ private setupInterceptors() { const transform = this.getTransform(); if (!transform) { return; } const { requestInterceptors, responseInterceptors, responseInterceptorsCatch } = transform; const axiosCanceler = new AxiosCanceler(); // TODO: 拦截配置升级了 请求拦截器 this.axiosInstance.interceptors.request.use((config: CreateAxiosOptions) => { // 如果ignoreCancelToken为true,则不添加到pending中 const ignoreCancelToken = config.requestOptions?.ignoreCancelToken; const ignoreCancel = ignoreCancelToken !== undefined ? ignoreCancelToken : this.options.requestOptions?.ignoreCancelToken; if (!ignoreCancel) { axiosCanceler.addPending(config); } if (requestInterceptors && isFunction(requestInterceptors)) { config = requestInterceptors(config, this.options); } // TODO: 拦截配置升级了,暂时 as 处理 return config as InternalAxiosRequestConfig; }, undefined); // 响应拦截器 this.axiosInstance.interceptors.response.use((res: AxiosResponse) => { if (res) { axiosCanceler.removePending(res.config); } if (responseInterceptors && isFunction(responseInterceptors)) { res = responseInterceptors(res); } return res; }, undefined); // 响应错误处理 if (responseInterceptorsCatch && isFunction(responseInterceptorsCatch)) { this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch); } } /** * @description: 文件上传 */ uploadFile( config: AxiosRequestConfig & RequestOptions, params: UploadFileParams, customFileKey = '', isMultiple = false ): Promise { const formData = new window.FormData(); const fileName = isMultiple ? 'files' : 'file'; if (customFileKey !== '') { params.fileList.forEach((file: File) => { formData.append(customFileKey, file); }); } else if (!isMultiple && !customFileKey) { params.fileList.forEach((file: File) => { formData.append(fileName, file); }); } else { params.fileList.forEach((item: any) => { formData.append(fileName, item.file, item.file.name); }); } if (params.request) { const requestData = JSON.stringify(params.request); formData.append('request', new Blob([requestData], { type: ContentTypeEnum.JSON })); } const transform = this.getTransform(); const { requestOptions } = this.options; const opt = { ...requestOptions, isTransformResponse: false }; const { transformRequestHook } = transform || {}; return new Promise((resolve, reject) => { this.axiosInstance .request>({ ...config, method: 'POST', data: formData, headers: { 'Content-type': ContentTypeEnum.FORM_DATA, }, // @ts-ignore requestOptions: { ignoreCancelToken: true, // 文件上传请求不需要添加到pending中,以免路由切换导致文件上传请求被取消 }, }) .then((res: AxiosResponse) => { // 请求成功后的处理 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); }) .catch((e: Error | AxiosError) => { if (axios.isAxiosError(e)) { // 在这可重写axios错误消息 // eslint-disable-next-line no-console console.log(e); } reject(e); }); }); } get(config: AxiosRequestConfig, options?: RequestOptions): Promise { return this.request({ ...config, method: 'GET' }, options); } post(config: AxiosRequestConfig, options?: RequestOptions): Promise { return this.request({ ...config, method: 'POST' }, options); } put(config: AxiosRequestConfig, options?: RequestOptions): Promise { return this.request({ ...config, method: 'PUT' }, options); } delete(config: AxiosRequestConfig, options?: RequestOptions): Promise { return this.request({ ...config, method: 'DELETE' }, options); } request(config: AxiosRequestConfig, options?: RequestOptions): Promise { let conf: CreateAxiosOptions = cloneDeep(config); const transform = this.getTransform(); const { requestOptions } = this.options; const opt = { ...requestOptions, ...options }; const { beforeRequestHook, transformRequestHook } = transform || {}; // 请求之前处理config if (beforeRequestHook && isFunction(beforeRequestHook)) { conf = beforeRequestHook(conf, opt); } conf.requestOptions = opt; return new Promise((resolve, reject) => { this.axiosInstance .request>(conf) .then((res: AxiosResponse) => { // 请求成功后的处理 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); }) .catch((e: Error | AxiosError) => { if (axios.isAxiosError(e)) { // 在这可重写axios错误消息 // eslint-disable-next-line no-console console.log(e); } reject(e); }); }); } }