溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Ant Design Pro 5 網(wǎng)絡(luò)請(qǐng)求和錯(cuò)誤處理是怎樣的

發(fā)布時(shí)間:2022-01-19 15:50:55 來(lái)源:億速云 閱讀:910 作者:柒染 欄目:開(kāi)發(fā)技術(shù)

本篇文章為大家展示了Ant Design Pro 5 網(wǎng)絡(luò)請(qǐng)求和錯(cuò)誤處理是怎樣的,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

Ant Design Pro 5 的網(wǎng)絡(luò)請(qǐng)求有點(diǎn)復(fù)雜,只看文檔不閱讀源碼搞不清楚到底發(fā)生了什么事情。涉及到fetch umi-request @umijs/plugin-request Ant Design Pro 5相關(guān)代碼。

fetch

代替XMLHttpRequest的訪(fǎng)問(wèn)和操縱HTTP的技術(shù)。fetch最大的問(wèn)題是,只有在發(fā)生網(wǎng)絡(luò)故障時(shí)或請(qǐng)求被阻止時(shí),才拋出異常;而對(duì)于 HTTP 狀態(tài)碼為 404 或 500 之類(lèi)的情況,會(huì)認(rèn)為是正常的響應(yīng),并不會(huì)拋出異常。

參考資料:Fetch API

umi-request

基于 fetch 封裝,提供諸如緩存、超時(shí)、字符編碼處理、錯(cuò)誤處理等功能。其中錯(cuò)誤處理與開(kāi)發(fā)緊密關(guān)聯(lián)。

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

/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;
      }
      // 對(duì)未知錯(cuò)誤進(jìn)行處理
      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上又進(jìn)行了封裝。umi-request提供了錯(cuò)誤處理機(jī)制,@umijs/plugin-request則提供了常規(guī)的錯(cuò)誤處理方法,并約定了服務(wù)器返回響應(yīng)的數(shù)據(jù)格式。還提供了useRequest。

需要特別注意的是,引用request時(shí),要引用@umijs/plugin-request,而不是umi-request,否則會(huì)發(fā)現(xiàn)request的行為與@umijs/plugin-request文檔描述的不一致。具體代碼如下:

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

數(shù)據(jù)格式

約定服務(wù)器返回的數(shù)據(jù)格式如下:

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
}

對(duì)于服務(wù)器返回的數(shù)據(jù)于這個(gè)格式不一致的,可以在A(yíng)nt Design Pro 5/src/app.tsx通過(guò)配置進(jìn)行適配。但此適配只作用于錯(cuò)誤處理,并影響接口返回的數(shù)據(jù)。所以在使用useRequest時(shí),這個(gè)適配并沒(méi)有用。

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

返回的數(shù)據(jù)格式中有success字段,用于描述請(qǐng)求是否成功。而umi-request對(duì)于http 2xx以外的響應(yīng)都會(huì)拋出異常,此處的success又有何用呢?答案是http 2xx的請(qǐng)求也可以返回success:false從而人為的拋出一個(gè)異常。

但我們并不建議這樣做,錯(cuò)誤的請(qǐng)求應(yīng)該返回http 2xx以外的響應(yīng),由umi-request自動(dòng)拋出一個(gè)異常。所以適配數(shù)據(jù)結(jié)構(gòu)時(shí),success可始終為true。

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

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

如服務(wù)器按照格式返回?cái)?shù)據(jù),則一切較為順利。但即使是正常的響應(yīng),也必須把數(shù)據(jù)包裝在data字段里,這樣在后端和前端都會(huì)感覺(jué)有些別扭。一般希望正常響應(yīng)直接返回?cái)?shù)據(jù),只有在發(fā)生錯(cuò)誤是,才返回類(lèi)似的數(shù)據(jù)格式。

錯(cuò)誤處理

錯(cuò)誤處理時(shí),也會(huì)調(diào)用上述的數(shù)據(jù)格式適配,所以并不是success不為false數(shù)據(jù)適配就無(wú)用了。主要從數(shù)據(jù)適配里獲得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,
  });

錯(cuò)誤顯示類(lèi)型

數(shù)據(jù)類(lèi)型中showType字段的值有以下幾個(gè),配合錯(cuò)誤處理方法,可以針對(duì)不同錯(cuò)誤類(lèi)型以不同的方式顯示。

export enum ErrorShowType {
  SILENT = 0, // 不提示錯(cuò)誤
  WARN_MESSAGE = 1, // 警告信息提示
  ERROR_MESSAGE = 2, // 錯(cuò)誤信息提示
  NOTIFICATION = 4, // 通知提示
  REDIRECT = 9, // 頁(yè)面跳轉(zhuǎn)
}

useRequest

安裝前面的數(shù)據(jù)格式約定,useRequest默認(rèn)從響應(yīng)數(shù)據(jù)里的data字段里獲取數(shù)據(jù)。如果服務(wù)器端是直接返回?cái)?shù)據(jù),則需要在A(yíng)nt Design Pro/config/config.ts配置:

  request: {
    dataField: '',
  }

需要注意,前面做的數(shù)據(jù)適配在useRequest里是無(wú)效的,不要認(rèn)為做了數(shù)據(jù)適配就萬(wàn)事大吉了。當(dāng)然服務(wù)器按照前面約定的數(shù)據(jù)格式返回?cái)?shù)據(jù)就沒(méi)這些煩惱了。

分頁(yè)數(shù)據(jù)結(jié)構(gòu)

Ant Design對(duì)分頁(yè)數(shù)據(jù)的結(jié)構(gòu)也有規(guī)定。

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

如不符合這個(gè)格式,可以在useRequest的formatResult進(jìn)行配置。如:

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

參考資料:

  • @umijs/plugin-request文檔

  • @umijs/plugin-request源碼

Ant Design Pro 5

提供了自定義錯(cuò)誤處理方法,和自定義數(shù)據(jù)格式的接口。默認(rèn)的演示代碼中,覆蓋了@umijs/plugin-request的錯(cuò)誤處理方法。如未注意到這點(diǎn),則會(huì)迷惑于A(yíng)nt Design Pro 5的錯(cuò)誤處理行為與@umijs/plugin-request文檔描述的并不一致,前面所述的錯(cuò)誤顯示類(lèi)型完全無(wú)效。

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: `請(qǐng)求錯(cuò)誤 ${status}: ${url}`,
      description: errorText,
    });
  }

  if (!response) {
    notification.error({
      description: '您的網(wǎng)絡(luò)發(fā)生異常,無(wú)法連接服務(wù)器',
      message: '網(wǎng)絡(luò)異常',
    });
  }
  throw error;
};

export const request: RequestConfig = {
  errorHandler,
};

上述內(nèi)容就是Ant Design Pro 5 網(wǎng)絡(luò)請(qǐng)求和錯(cuò)誤處理是怎樣的,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI