Forráskód Böngészése

refactor(axios): control the display of common errors in the request cycle (#758)

Co-authored-by: frankylli <frankylli@tencent.com>
xlaoyu 3 éve
szülő
commit
49b66e83ac

+ 1 - 1
src/locales/lang/zh_CN/sys.ts

@@ -7,7 +7,7 @@ export default {
     apiTimeoutMessage: '接口请求超时,请刷新页面重试!',
     apiRequestFailed: '请求出错,请稍候重试',
     networkException: '网络异常',
-    networkExceptionMsg: '请检查您的网络连接是否正常!',
+    networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!',
 
     errMsg401: '用户没有权限(令牌、用户名、密码错误)!',
     errMsg403: '用户得到授权,但是访问是被禁止的。!',

+ 3 - 2
src/utils/http/axios/Axios.ts

@@ -188,7 +188,7 @@ export class VAxios {
   }
 
   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;
@@ -199,6 +199,7 @@ export class VAxios {
     if (beforeRequestHook && isFunction(beforeRequestHook)) {
       conf = beforeRequestHook(conf, opt);
     }
+    conf.requestOptions = opt;
 
     conf = this.supportFormData(conf);
 
@@ -219,7 +220,7 @@ export class VAxios {
         })
         .catch((e: Error) => {
           if (requestCatchHook && isFunction(requestCatchHook)) {
-            reject(requestCatchHook(e));
+            reject(requestCatchHook(e, opt));
             return;
           }
           reject(e);

+ 1 - 1
src/utils/http/axios/axiosTransform.ts

@@ -25,7 +25,7 @@ export abstract class AxiosTransform {
   /**
    * @description: 请求失败处理
    */
-  requestCatchHook?: (e: Error) => Promise<any>;
+  requestCatchHook?: (e: Error, options: RequestOptions) => Promise<any>;
 
   /**
    * @description: 请求之前的拦截器

+ 30 - 14
src/utils/http/axios/checkStatus.ts

@@ -1,58 +1,74 @@
+import type { ErrorMessageMode } from './types';
+
 import { useMessage } from '/@/hooks/web/useMessage';
 import { useI18n } from '/@/hooks/web/useI18n';
 // import router from '/@/router';
 // import { PageEnum } from '/@/enums/pageEnum';
 import { useUserStoreWidthOut } from '/@/store/modules/user';
 
-const { createMessage } = useMessage();
+const { createMessage, createErrorModal } = useMessage();
 
 const error = createMessage.error!;
-export function checkStatus(status: number, msg: string): void {
+export function checkStatus(
+  status: number,
+  msg: string,
+  errorMessageMode: ErrorMessageMode = 'message'
+): void {
   const { t } = useI18n();
   const userStore = useUserStoreWidthOut();
+  let errMessage = '';
+
   switch (status) {
     case 400:
-      error(`${msg}`);
+      errMessage = `${msg}`;
       break;
     // 401: Not logged in
     // Jump to the login page if not logged in, and carry the path of the current page
     // Return to the current page after successful login. This step needs to be operated on the login page.
     case 401:
-      error(t('sys.api.errMsg401'));
+      errMessage = t('sys.api.errMsg401');
       userStore.setToken(undefined);
       userStore.setSessionTimeout(true);
       break;
     case 403:
-      error(t('sys.api.errMsg403'));
+      errMessage = t('sys.api.errMsg403');
       break;
     // 404请求不存在
     case 404:
-      error(t('sys.api.errMsg404'));
+      errMessage = t('sys.api.errMsg404');
       break;
     case 405:
-      error(t('sys.api.errMsg405'));
+      errMessage = t('sys.api.errMsg405');
       break;
     case 408:
-      error(t('sys.api.errMsg408'));
+      errMessage = t('sys.api.errMsg408');
       break;
     case 500:
-      error(t('sys.api.errMsg500'));
+      errMessage = t('sys.api.errMsg500');
       break;
     case 501:
-      error(t('sys.api.errMsg501'));
+      errMessage = t('sys.api.errMsg501');
       break;
     case 502:
-      error(t('sys.api.errMsg502'));
+      errMessage = t('sys.api.errMsg502');
       break;
     case 503:
-      error(t('sys.api.errMsg503'));
+      errMessage = t('sys.api.errMsg503');
       break;
     case 504:
-      error(t('sys.api.errMsg504'));
+      errMessage = t('sys.api.errMsg504');
       break;
     case 505:
-      error(t('sys.api.errMsg505'));
+      errMessage = t('sys.api.errMsg505');
       break;
     default:
   }
+
+  if (errMessage) {
+    if (errorMessageMode === 'modal') {
+      createErrorModal({ title: t('sys.api.errorTip'), content: errMessage });
+    } else if (errorMessageMode === 'message') {
+      error(errMessage);
+    }
+  }
 }

+ 37 - 21
src/utils/http/axios/index.ts

@@ -62,26 +62,25 @@ const transform: AxiosTransform = {
 
     // 在此处根据自己项目的实际情况对不同的code执行不同的操作
     // 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
+    let timeoutMsg = '';
     switch (code) {
       case ResultEnum.TIMEOUT:
-        const timeoutMsg = t('sys.api.timeoutMessage');
-        createErrorModal({
-          title: t('sys.api.operationFailed'),
-          content: timeoutMsg,
-        });
-        throw new Error(timeoutMsg);
+        timeoutMsg = t('sys.api.timeoutMessage');
       default:
         if (message) {
-          // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
-          // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示
-          if (options.errorMessageMode === 'modal') {
-            createErrorModal({ title: t('sys.api.errorTip'), content: message });
-          } else if (options.errorMessageMode === 'message') {
-            createMessage.error(message);
-          }
+          timeoutMsg = message;
         }
     }
-    throw new Error(message || t('sys.api.apiRequestFailed'));
+
+    // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
+    // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示
+    if (options.errorMessageMode === 'modal') {
+      createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg });
+    } else if (options.errorMessageMode === 'message') {
+      createMessage.error(timeoutMsg);
+    }
+
+    throw new Error(timeoutMsg || t('sys.api.apiRequestFailed'));
   },
 
   // 请求之前处理config
@@ -136,29 +135,46 @@ const transform: AxiosTransform = {
   },
 
   /**
+   * @description: 响应拦截器处理
+   */
+  responseInterceptors: (res: AxiosResponse<any>) => {
+    return res;
+  },
+
+  /**
    * @description: 响应错误处理
    */
   responseInterceptorsCatch: (error: any) => {
     const { t } = useI18n();
     const errorLogStore = useErrorLogStoreWithOut();
     errorLogStore.addAjaxErrorInfo(error);
-    const { response, code, message } = error || {};
+    const { response, code, message, config } = error || {};
+    const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
     const msg: string = response?.data?.error?.message ?? '';
     const err: string = error?.toString?.() ?? '';
+    let errMessage = '';
+
     try {
       if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
-        createMessage.error(t('sys.api.apiTimeoutMessage'));
+        errMessage = t('sys.api.apiTimeoutMessage');
       }
       if (err?.includes('Network Error')) {
-        createErrorModal({
-          title: t('sys.api.networkException'),
-          content: t('sys.api.networkExceptionMsg'),
-        });
+        errMessage = t('sys.api.networkExceptionMsg');
+      }
+
+      if (errMessage) {
+        if (errorMessageMode === 'modal') {
+          createErrorModal({ title: t('sys.api.errorTip'), content: errMessage });
+        } else if (errorMessageMode === 'message') {
+          createMessage.error(errMessage);
+        }
+        return Promise.reject(error);
       }
     } catch (error) {
       throw new Error(error);
     }
-    checkStatus(error?.response?.status, msg);
+
+    checkStatus(error?.response?.status, msg, errorMessageMode);
     return Promise.reject(error);
   },
 };