Axios.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios';
  2. import axios from 'axios';
  3. import { AxiosCanceler } from './axiosCancel';
  4. import { isFunction } from '/@/utils/is';
  5. import { cloneDeep } from 'lodash-es';
  6. import type { RequestOptions, CreateAxiosOptions, Result, UploadFileParams } from './types';
  7. import { errorResult } from './const';
  8. import { ContentTypeEnum } from '/@/enums/httpEnum';
  9. import qs from 'qs';
  10. import { RequestEnum } from '../../../enums/httpEnum';
  11. export * from './axiosTransform';
  12. /**
  13. * @description: axios module
  14. */
  15. export class VAxios {
  16. private axiosInstance: AxiosInstance;
  17. private readonly options: CreateAxiosOptions;
  18. constructor(options: CreateAxiosOptions) {
  19. this.options = options;
  20. this.axiosInstance = axios.create(options);
  21. this.setupInterceptors();
  22. }
  23. /**
  24. * @description: Create axios instance
  25. */
  26. private createAxios(config: CreateAxiosOptions): void {
  27. this.axiosInstance = axios.create(config);
  28. }
  29. private getTransform() {
  30. const { transform } = this.options;
  31. return transform;
  32. }
  33. getAxios(): AxiosInstance {
  34. return this.axiosInstance;
  35. }
  36. /**
  37. * @description: Reconfigure axios
  38. */
  39. configAxios(config: CreateAxiosOptions) {
  40. if (!this.axiosInstance) {
  41. return;
  42. }
  43. this.createAxios(config);
  44. }
  45. /**
  46. * @description: Set general header
  47. */
  48. setHeader(headers: any): void {
  49. if (!this.axiosInstance) {
  50. return;
  51. }
  52. Object.assign(this.axiosInstance.defaults.headers, headers);
  53. }
  54. /**
  55. * @description: Interceptor configuration
  56. */
  57. private setupInterceptors() {
  58. const transform = this.getTransform();
  59. if (!transform) {
  60. return;
  61. }
  62. const {
  63. requestInterceptors,
  64. requestInterceptorsCatch,
  65. responseInterceptors,
  66. responseInterceptorsCatch,
  67. } = transform;
  68. const axiosCanceler = new AxiosCanceler();
  69. // Request interceptor configuration processing
  70. this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
  71. // If cancel repeat request is turned on, then cancel repeat request is prohibited
  72. const {
  73. headers: { ignoreCancelToken = false },
  74. } = config;
  75. !ignoreCancelToken && axiosCanceler.addPending(config);
  76. if (requestInterceptors && isFunction(requestInterceptors)) {
  77. config = requestInterceptors(config);
  78. }
  79. return config;
  80. }, undefined);
  81. // Request interceptor error capture
  82. requestInterceptorsCatch &&
  83. isFunction(requestInterceptorsCatch) &&
  84. this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch);
  85. // Response result interceptor processing
  86. this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => {
  87. res && axiosCanceler.removePending(res.config);
  88. if (responseInterceptors && isFunction(responseInterceptors)) {
  89. res = responseInterceptors(res);
  90. }
  91. return res;
  92. }, undefined);
  93. // Response result interceptor error capture
  94. responseInterceptorsCatch &&
  95. isFunction(responseInterceptorsCatch) &&
  96. this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch);
  97. }
  98. /**
  99. * @description: File Upload
  100. */
  101. uploadFile<T = any>(config: AxiosRequestConfig, params: UploadFileParams) {
  102. const formData = new window.FormData();
  103. if (params.data) {
  104. Object.keys(params.data).forEach((key) => {
  105. if (!params.data) return;
  106. const value = params.data[key];
  107. if (Array.isArray(value)) {
  108. value.forEach((item) => {
  109. formData.append(`${key}[]`, item);
  110. });
  111. return;
  112. }
  113. formData.append(key, params.data[key]);
  114. });
  115. }
  116. formData.append(params.name || 'file', params.file, params.filename);
  117. return this.axiosInstance.request<T>({
  118. ...config,
  119. method: 'POST',
  120. data: formData,
  121. headers: {
  122. 'Content-type': ContentTypeEnum.FORM_DATA,
  123. ignoreCancelToken: true,
  124. },
  125. });
  126. }
  127. // support form-data
  128. supportFormData(config: AxiosRequestConfig) {
  129. const headers = this.options?.headers;
  130. const contentType = headers?.['Content-Type'] || headers?.['content-type'];
  131. if (
  132. contentType !== ContentTypeEnum.FORM_URLENCODED ||
  133. !Reflect.has(config, 'data') ||
  134. config.method?.toUpperCase() === RequestEnum.GET
  135. ) {
  136. return config;
  137. }
  138. return {
  139. ...config,
  140. data: qs.stringify(config.data),
  141. };
  142. }
  143. request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
  144. let conf: AxiosRequestConfig = cloneDeep(config);
  145. const transform = this.getTransform();
  146. const { requestOptions } = this.options;
  147. const opt: RequestOptions = Object.assign({}, requestOptions, options);
  148. const { beforeRequestHook, requestCatch, transformRequestData } = transform || {};
  149. if (beforeRequestHook && isFunction(beforeRequestHook)) {
  150. conf = beforeRequestHook(conf, opt);
  151. }
  152. conf = this.supportFormData(conf);
  153. return new Promise((resolve, reject) => {
  154. this.axiosInstance
  155. .request<any, AxiosResponse<Result>>(conf)
  156. .then((res: AxiosResponse<Result>) => {
  157. if (transformRequestData && isFunction(transformRequestData)) {
  158. const ret = transformRequestData(res, opt);
  159. ret !== errorResult ? resolve(ret) : reject(new Error('request error!'));
  160. return;
  161. }
  162. resolve((res as unknown) as Promise<T>);
  163. })
  164. .catch((e: Error) => {
  165. if (requestCatch && isFunction(requestCatch)) {
  166. reject(requestCatch(e));
  167. return;
  168. }
  169. reject(e);
  170. });
  171. });
  172. }
  173. }