Axios.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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 { ContentTypeEnum } from '@/enums/httpEnum';
  8. export * from './axiosTransform';
  9. /**
  10. * @description: axios模块
  11. */
  12. export class VAxios {
  13. private axiosInstance: AxiosInstance;
  14. private options: CreateAxiosOptions;
  15. constructor(options: CreateAxiosOptions) {
  16. this.options = options;
  17. this.axiosInstance = axios.create(options);
  18. this.setupInterceptors();
  19. }
  20. getAxios(): AxiosInstance {
  21. return this.axiosInstance;
  22. }
  23. /**
  24. * @description: 重新配置axios
  25. */
  26. configAxios(config: CreateAxiosOptions) {
  27. if (!this.axiosInstance) {
  28. return;
  29. }
  30. this.createAxios(config);
  31. }
  32. /**
  33. * @description: 设置通用header
  34. */
  35. setHeader(headers: any): void {
  36. if (!this.axiosInstance) {
  37. return;
  38. }
  39. Object.assign(this.axiosInstance.defaults.headers, headers);
  40. }
  41. /**
  42. * @description: 请求方法
  43. */
  44. request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
  45. let conf: AxiosRequestConfig = cloneDeep(config);
  46. const transform = this.getTransform();
  47. const { requestOptions } = this.options;
  48. const opt: RequestOptions = Object.assign({}, requestOptions, options);
  49. const { beforeRequestHook, requestCatch, transformRequestData } = transform || {};
  50. if (beforeRequestHook && isFunction(beforeRequestHook)) {
  51. conf = beforeRequestHook(conf, opt);
  52. }
  53. //这里重新 赋值成最新的配置
  54. // @ts-ignore
  55. conf.requestOptions = opt;
  56. return new Promise((resolve, reject) => {
  57. this.axiosInstance
  58. .request<any, AxiosResponse<Result>>(conf)
  59. .then((res: AxiosResponse<Result>) => {
  60. // 请求是否被取消
  61. const isCancel = axios.isCancel(res);
  62. if (transformRequestData && isFunction(transformRequestData) && !isCancel) {
  63. try {
  64. const ret = transformRequestData(res, opt);
  65. resolve(ret);
  66. } catch (err) {
  67. reject(err || new Error('request error!'));
  68. }
  69. return;
  70. }
  71. resolve(res as unknown as Promise<T>);
  72. })
  73. .catch((e: Error) => {
  74. if (requestCatch && isFunction(requestCatch)) {
  75. reject(requestCatch(e));
  76. return;
  77. }
  78. reject(e);
  79. });
  80. });
  81. }
  82. /**
  83. * @description: 创建axios实例
  84. */
  85. private createAxios(config: CreateAxiosOptions): void {
  86. this.axiosInstance = axios.create(config);
  87. }
  88. private getTransform() {
  89. const { transform } = this.options;
  90. return transform;
  91. }
  92. /**
  93. * @description: 文件上传
  94. */
  95. uploadFile<T = any>(config: AxiosRequestConfig, params: UploadFileParams) {
  96. const formData = new window.FormData();
  97. const customFilename = params.name || 'file';
  98. if (params.filename) {
  99. formData.append(customFilename, params.file, params.filename);
  100. } else {
  101. formData.append(customFilename, params.file);
  102. }
  103. if (params.data) {
  104. Object.keys(params.data).forEach((key) => {
  105. const value = params.data![key];
  106. if (Array.isArray(value)) {
  107. value.forEach((item) => {
  108. formData.append(`${key}[]`, item);
  109. });
  110. return;
  111. }
  112. formData.append(key, params.data![key]);
  113. });
  114. }
  115. return this.axiosInstance.request<T>({
  116. method: 'POST',
  117. data: formData,
  118. headers: {
  119. 'Content-type': ContentTypeEnum.FORM_DATA,
  120. ignoreCancelToken: true,
  121. },
  122. ...config,
  123. });
  124. }
  125. /**
  126. * @description: 拦截器配置
  127. */
  128. private setupInterceptors() {
  129. const transform = this.getTransform();
  130. if (!transform) {
  131. return;
  132. }
  133. const {
  134. requestInterceptors,
  135. requestInterceptorsCatch,
  136. responseInterceptors,
  137. responseInterceptorsCatch,
  138. } = transform;
  139. const axiosCanceler = new AxiosCanceler();
  140. // 请求拦截器配置处理
  141. this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
  142. const {
  143. headers: { ignoreCancelToken },
  144. } = config;
  145. const ignoreCancel =
  146. ignoreCancelToken !== undefined
  147. ? ignoreCancelToken
  148. : this.options.requestOptions?.ignoreCancelToken;
  149. !ignoreCancel && axiosCanceler.addPending(config);
  150. if (requestInterceptors && isFunction(requestInterceptors)) {
  151. config = requestInterceptors(config, this.options);
  152. }
  153. return config;
  154. }, undefined);
  155. // 请求拦截器错误捕获
  156. requestInterceptorsCatch &&
  157. isFunction(requestInterceptorsCatch) &&
  158. this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch);
  159. // 响应结果拦截器处理
  160. this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => {
  161. res && axiosCanceler.removePending(res.config);
  162. if (responseInterceptors && isFunction(responseInterceptors)) {
  163. res = responseInterceptors(res);
  164. }
  165. return res;
  166. }, undefined);
  167. // 响应结果拦截器错误捕获
  168. responseInterceptorsCatch &&
  169. isFunction(responseInterceptorsCatch) &&
  170. this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch);
  171. }
  172. }