溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Ant Design Pro 5 網絡請求和錯誤處理是怎樣的

發布時間:2022-01-19 15:50:55 來源:億速云 閱讀:980 作者:柒染 欄目:開發技術

本篇文章為大家展示了Ant Design Pro 5 網絡請求和錯誤處理是怎樣的,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

Ant Design Pro 5 的網絡請求有點復雜,只看文檔不閱讀源碼搞不清楚到底發生了什么事情。涉及到fetch umi-request @umijs/plugin-request Ant Design Pro 5相關代碼。

fetch

代替XMLHttpRequest的訪問和操縱HTTP的技術。fetch最大的問題是,只有在發生網絡故障時或請求被阻止時,才拋出異常;而對于 HTTP 狀態碼為 404 或 500 之類的情況,會認為是正常的響應,并不會拋出異常。

參考資料:Fetch API

umi-request

基于 fetch 封裝,提供諸如緩存、超時、字符編碼處理、錯誤處理等功能。其中錯誤處理與開發緊密關聯。

為了解決fetch在非成功狀態碼下,不拋出異常的情況,umi-request會判斷HTTP狀態碼是否為2xx;如果不是,則會拋出異常。并且對fetch自己拋出的異常也進行了處理,加上了更多信息,便于后續的處理。

/src/middleware/parseResponse.js

    ...
    .then(body => {
      ...
      if (copy.status >= 200 && copy.status < 300) {
        // 提供源response, 以便自定義處理
        if (getResponse) {
          ctx.res = { data: body, response: copy };
          return;
        }
        ctx.res = body;
        return;
      }
      throw new ResponseError(copy, 'http error', body, req, 'HttpError');
    })
    .catch(e => {
      if (e instanceof RequestError || e instanceof ResponseError) {
        throw e;
      }
      // 對未知錯誤進行處理
      const { req, res } = ctx;
      e.request = e.request || req;
      e.response = e.response || res;
      e.type = e.type || e.name;
      e.data = e.data || undefined;
      throw e;
    });
    ...

參考資料:umi-request

@umijs/plugin-request

@umijs/plugin-request則在umi-request上又進行了封裝。umi-request提供了錯誤處理機制,@umijs/plugin-request則提供了常規的錯誤處理方法,并約定了服務器返回響應的數據格式。還提供了useRequest。

需要特別注意的是,引用request時,要引用@umijs/plugin-request,而不是umi-request,否則會發現request的行為與@umijs/plugin-request文檔描述的不一致。具體代碼如下:

// 引用 umi-request 的 request。錯誤?。?!
import request from 'umi-request';
// 引用 @umijs/plugin-request 的 reqeust。正確。
import {request} from 'umi';

數據格式

約定服務器返回的數據格式如下:

interface ErrorInfoStructure {
  success: boolean; // if request is success
  data?: any; // response data
  errorCode?: string; // code for errorType
  errorMessage?: string; // message display to user 
  showType?: number; // error display type: 0 silent; 1 message.warn; 2 message.error; 4 notification; 9 page
  traceId?: string; // Convenient for back-end Troubleshooting: unique request ID
  host?: string; // onvenient for backend Troubleshooting: host of current access server
}

對于服務器返回的數據于這個格式不一致的,可以在Ant Design Pro 5/src/app.tsx通過配置進行適配。但此適配只作用于錯誤處理,并影響接口返回的數據。所以在使用useRequest時,這個適配并沒有用。

export const request: RequestConfig = {
  errorConfig: {
    adaptor: (resData) => {
      return {
        ...resData,
        success: resData.ok,
        errorMessage: resData.message,
      };
    },
  },
};

返回的數據格式中有success字段,用于描述請求是否成功。而umi-request對于http 2xx以外的響應都會拋出異常,此處的success又有何用呢?答案是http 2xx的請求也可以返回success:false從而人為的拋出一個異常。

但我們并不建議這樣做,錯誤的請求應該返回http 2xx以外的響應,由umi-request自動拋出一個異常。所以適配數據結構時,success可始終為true。

/umijs/plugins/blob/master/packages/plugin-request/src/request.ts

  ...
  const errorAdaptor = requestConfig.errorConfig?.adaptor || (resData => resData);
  ...
  // 中間件統一錯誤處理
  // 后端返回格式 { success: boolean, data: any }
  // 按照項目具體情況修改該部分邏輯
  requestMethodInstance.use(async (ctx, next) => {
    ...
    const errorInfo = errorAdaptor(resData, ctx);
    if (errorInfo.success === false) {
      // 拋出錯誤到 errorHandler 中處理
      const error: RequestError = new Error(errorInfo.errorMessage);
      error.name = 'BizError';
      error.data = resData;
      error.info = errorInfo;
      throw error;
    }
  });

如服務器按照格式返回數據,則一切較為順利。但即使是正常的響應,也必須把數據包裝在data字段里,這樣在后端和前端都會感覺有些別扭。一般希望正常響應直接返回數據,只有在發生錯誤是,才返回類似的數據格式。

錯誤處理

錯誤處理時,也會調用上述的數據格式適配,所以并不是success不為false數據適配就無用了。主要從數據適配里獲得showType errorMessage errorCode。

/umijs/plugins/blob/master/packages/plugin-request/src/request.ts

const errorAdaptor = requestConfig.errorConfig?.adaptor || (resData => resData);
requestMethodInstance = extend({
    errorHandler: (error: RequestError) => {
      // @ts-ignore
      if (error?.request?.options?.skipErrorHandler) {
        throw error;
      }
      let errorInfo: ErrorInfoStructure | undefined;
      if (error.name === 'ResponseError' && error.data && error.request) {
        const ctx: Context = {
          req: error.request,
          res: error.response,
        };
        errorInfo = errorAdaptor(error.data, ctx);
        error.message = errorInfo?.errorMessage || error.message;
        error.data = error.data;
        error.info = errorInfo;
      }
      errorInfo = error.info;

      if (errorInfo) {
        const errorMessage = errorInfo?.errorMessage;
        const errorCode = errorInfo?.errorCode;
        const errorPage =
          requestConfig.errorConfig?.errorPage || DEFAULT_ERROR_PAGE;

        switch (errorInfo?.showType) {
          case ErrorShowType.SILENT:
            // do nothing
            break;
          case ErrorShowType.WARN_MESSAGE:
            message.warn(errorMessage);
            break;
          case ErrorShowType.ERROR_MESSAGE:
            message.error(errorMessage);
            break;
          case ErrorShowType.NOTIFICATION:
            notification.open({
              message: errorMessage,
            });
            break;
          case ErrorShowType.REDIRECT:
            // @ts-ignore
            history.push({
              pathname: errorPage,
              query: { errorCode, errorMessage },
            });
            // redirect to error page
            break;
          default:
            message.error(errorMessage);
            break;
        }
      } else {
        message.error(error.message || 'Request error, please retry.');
      }
      throw error;
    },
    ...requestConfig,
  });

錯誤顯示類型

數據類型中showType字段的值有以下幾個,配合錯誤處理方法,可以針對不同錯誤類型以不同的方式顯示。

export enum ErrorShowType {
  SILENT = 0, // 不提示錯誤
  WARN_MESSAGE = 1, // 警告信息提示
  ERROR_MESSAGE = 2, // 錯誤信息提示
  NOTIFICATION = 4, // 通知提示
  REDIRECT = 9, // 頁面跳轉
}

useRequest

安裝前面的數據格式約定,useRequest默認從響應數據里的data字段里獲取數據。如果服務器端是直接返回數據,則需要在Ant Design Pro/config/config.ts配置:

  request: {
    dataField: '',
  }

需要注意,前面做的數據適配在useRequest里是無效的,不要認為做了數據適配就萬事大吉了。當然服務器按照前面約定的數據格式返回數據就沒這些煩惱了。

分頁數據結構

Ant Design對分頁數據的結構也有規定。

{
   list: [],
   current?: number,
   pageSize?: number,
   total?: number,
}

如不符合這個格式,可以在useRequest的formatResult進行配置。如:

const { data, loading } = useRequest(() => {
  return services.getUserList('/api/test');
},{
  formatResult: (result) => {
    return ...
  }
});

參考資料:

  • @umijs/plugin-request文檔

  • @umijs/plugin-request源碼

Ant Design Pro 5

提供了自定義錯誤處理方法,和自定義數據格式的接口。默認的演示代碼中,覆蓋了@umijs/plugin-request的錯誤處理方法。如未注意到這點,則會迷惑于Ant Design Pro 5的錯誤處理行為與@umijs/plugin-request文檔描述的并不一致,前面所述的錯誤顯示類型完全無效。

Ant Design Pro/config/config.ts

const errorHandler = (error: ResponseError) => {
  const { response } = error;
  if (response && response.status) {
    const errorText = codeMessage[response.status] || response.statusText;
    const { status, url } = response;

    notification.error({
      message: `請求錯誤 ${status}: ${url}`,
      description: errorText,
    });
  }

  if (!response) {
    notification.error({
      description: '您的網絡發生異常,無法連接服務器',
      message: '網絡異常',
    });
  }
  throw error;
};

export const request: RequestConfig = {
  errorHandler,
};

上述內容就是Ant Design Pro 5 網絡請求和錯誤處理是怎樣的,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女