huangyinfeng
2024-09-04 faf7614d01644b174a76cb7c444c960bd6ff75c1
提交 | 用户 | age
ccaa84 1 import type {
KL 2   AxiosRequestConfig,
3   AxiosInstance,
4   AxiosResponse,
5   AxiosError,
6   InternalAxiosRequestConfig,
7 } from 'axios';
4d2fb0 8 import type { RequestOptions, Result, UploadFileParams } from '#/axios';
970d40 9 import type { CreateAxiosOptions } from './axiosTransform';
2f6253 10 import axios from 'axios';
970d40 11 import qs from 'qs';
2f6253 12 import { AxiosCanceler } from './axiosCancel';
4d2fb0 13 import { isFunction } from '@/utils/is';
935d4f 14 import { cloneDeep } from 'lodash-es';
4d2fb0 15 import { ContentTypeEnum, RequestEnum } from '@/enums/httpEnum';
2f6253 16
17 export * from './axiosTransform';
18
128809 19
2f6253 20 /**
589409 21  * @description:  axios module
2f6253 22  */
23 export class VAxios {
24   private axiosInstance: AxiosInstance;
ecfb70 25   private readonly options: CreateAxiosOptions;
2f6253 26
27   constructor(options: CreateAxiosOptions) {
28     this.options = options;
29     this.axiosInstance = axios.create(options);
30     this.setupInterceptors();
31   }
32
33   /**
589409 34    * @description:  Create axios instance
2f6253 35    */
36   private createAxios(config: CreateAxiosOptions): void {
37     this.axiosInstance = axios.create(config);
38   }
39
40   private getTransform() {
41     const { transform } = this.options;
42     return transform;
43   }
44
45   getAxios(): AxiosInstance {
46     return this.axiosInstance;
47   }
48
49   /**
589409 50    * @description: Reconfigure axios
2f6253 51    */
52   configAxios(config: CreateAxiosOptions) {
53     if (!this.axiosInstance) {
54       return;
55     }
56     this.createAxios(config);
57   }
58
59   /**
589409 60    * @description: Set general header
2f6253 61    */
62   setHeader(headers: any): void {
63     if (!this.axiosInstance) {
64       return;
65     }
66     Object.assign(this.axiosInstance.defaults.headers, headers);
67   }
68
69   /**
19dc88 70    * @description: Interceptor configuration 拦截器配置
2f6253 71    */
72   private setupInterceptors() {
ccaa84 73     // const transform = this.getTransform();
KL 74     const {
75       axiosInstance,
76       options: { transform },
77     } = this;
2f6253 78     if (!transform) {
79       return;
80     }
81     const {
82       requestInterceptors,
83       requestInterceptorsCatch,
84       responseInterceptors,
85       responseInterceptorsCatch,
86     } = transform;
87
88     const axiosCanceler = new AxiosCanceler();
89
589409 90     // Request interceptor configuration processing
ccaa84 91     this.axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
a95308 92       // If cancel repeat request is turned on, then cancel repeat request is prohibited
HJ 93       const requestOptions =
94         (config as unknown as any).requestOptions ?? this.options.requestOptions;
ccaa84 95       const ignoreCancelToken = requestOptions?.ignoreCancelToken ?? true;
3b8ca4 96
ccaa84 97       !ignoreCancelToken && axiosCanceler.addPending(config);
KL 98
2f6253 99       if (requestInterceptors && isFunction(requestInterceptors)) {
b6d5b0 100         config = requestInterceptors(config, this.options);
2f6253 101       }
102       return config;
103     }, undefined);
104
589409 105     // Request interceptor error capture
2f6253 106     requestInterceptorsCatch &&
107       isFunction(requestInterceptorsCatch) &&
108       this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch);
109
589409 110     // Response result interceptor processing
2f6253 111     this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => {
112       res && axiosCanceler.removePending(res.config);
113       if (responseInterceptors && isFunction(responseInterceptors)) {
114         res = responseInterceptors(res);
115       }
116       return res;
117     }, undefined);
118
589409 119     // Response result interceptor error capture
2f6253 120     responseInterceptorsCatch &&
121       isFunction(responseInterceptorsCatch) &&
136cbb 122       this.axiosInstance.interceptors.response.use(undefined, (error) => {
ccaa84 123         return responseInterceptorsCatch(axiosInstance, error);
136cbb 124       });
2f6253 125   }
126
746d4a 127   /**
589409 128    * @description:  File Upload
746d4a 129    */
J 130   uploadFile<T = any>(config: AxiosRequestConfig, params: UploadFileParams) {
131     const formData = new window.FormData();
935d4f 132     const customFilename = params.name || 'file';
E 133
134     if (params.filename) {
135       formData.append(customFilename, params.file, params.filename);
136     } else {
137       formData.append(customFilename, params.file);
138     }
2f6253 139
746d4a 140     if (params.data) {
J 141       Object.keys(params.data).forEach((key) => {
935d4f 142         const value = params.data![key];
746d4a 143         if (Array.isArray(value)) {
J 144           value.forEach((item) => {
145             formData.append(`${key}[]`, item);
146           });
147           return;
148         }
2f6253 149
935d4f 150         formData.append(key, params.data![key]);
746d4a 151       });
J 152     }
153
154     return this.axiosInstance.request<T>({
155       ...config,
156       method: 'POST',
157       data: formData,
158       headers: {
159         'Content-type': ContentTypeEnum.FORM_DATA,
a248e2 160         // @ts-ignore
746d4a 161         ignoreCancelToken: true,
J 162       },
163     });
164   }
2f6253 165
c41fa7 166   // support form-data
V 167   supportFormData(config: AxiosRequestConfig) {
5724bc 168     const headers = config.headers || this.options.headers;
c41fa7 169     const contentType = headers?.['Content-Type'] || headers?.['content-type'];
V 170
171     if (
172       contentType !== ContentTypeEnum.FORM_URLENCODED ||
173       !Reflect.has(config, 'data') ||
174       config.method?.toUpperCase() === RequestEnum.GET
175     ) {
176       return config;
177     }
178
179     return {
180       ...config,
e1b30a 181       data: qs.stringify(config.data, { arrayFormat: 'brackets' }),
c41fa7 182     };
V 183   }
184
a821d9 185   get<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
V 186     return this.request({ ...config, method: 'GET' }, options);
187   }
188
189   post<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
190     return this.request({ ...config, method: 'POST' }, options);
191   }
192
193   put<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
194     return this.request({ ...config, method: 'PUT' }, options);
195   }
196
197   delete<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
198     return this.request({ ...config, method: 'DELETE' }, options);
199   }
200
2f6253 201   request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
49b66e 202     let conf: CreateAxiosOptions = cloneDeep(config);
c70cf3 203     // cancelToken 如果被深拷贝,会导致最外层无法使用cancel方法来取消请求
ba2415 204     if (config.cancelToken) {
V 205       conf.cancelToken = config.cancelToken;
c70cf3 206     }
a95308 207
b43fe7 208     if (config.signal) {
L 209       conf.signal = config.signal;
210     }
ba2415 211
2f6253 212     const transform = this.getTransform();
213
214     const { requestOptions } = this.options;
215
216     const opt: RequestOptions = Object.assign({}, requestOptions, options);
217
c0e40f 218     const { beforeRequestHook, requestCatchHook, transformResponseHook } = transform || {};
2f6253 219     if (beforeRequestHook && isFunction(beforeRequestHook)) {
220       conf = beforeRequestHook(conf, opt);
221     }
49b66e 222     conf.requestOptions = opt;
c41fa7 223
V 224     conf = this.supportFormData(conf);
11d3f3 225
2f6253 226     return new Promise((resolve, reject) => {
227       this.axiosInstance
228         .request<any, AxiosResponse<Result>>(conf)
229         .then((res: AxiosResponse<Result>) => {
c0e40f 230           if (transformResponseHook && isFunction(transformResponseHook)) {
b218f1 231             try {
c0e40f 232               const ret = transformResponseHook(res, opt);
b218f1 233               resolve(ret);
N 234             } catch (err) {
235               reject(err || new Error('request error!'));
236             }
2f6253 237             return;
238           }
b218f1 239           resolve(res as unknown as Promise<T>);
2f6253 240         })
72634f 241         .catch((e: Error | AxiosError) => {
a821d9 242           if (requestCatchHook && isFunction(requestCatchHook)) {
49b66e 243             reject(requestCatchHook(e, opt));
2f6253 244             return;
245           }
72634f 246           if (axios.isAxiosError(e)) {
C 247             // rewrite error message from axios in here
248           }
2f6253 249           reject(e);
250         });
251     });
252   }
253 }