本篇文章為大家展示了Ant Design Pro 5 網絡請求和錯誤處理是怎樣的,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
Ant Design Pro 5 的網絡請求有點復雜,只看文檔不閱讀源碼搞不清楚到底發生了什么事情。涉及到fetch umi-request @umijs/plugin-request Ant Design Pro 5相關代碼。
代替XMLHttpRequest的訪問和操縱HTTP的技術。fetch最大的問題是,只有在發生網絡故障時或請求被阻止時,才拋出異常;而對于 HTTP 狀態碼為 404 或 500 之類的情況,會認為是正常的響應,并不會拋出異常。
參考資料:Fetch API
基于 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則在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默認從響應數據里的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源碼
提供了自定義錯誤處理方法,和自定義數據格式的接口。默認的演示代碼中,覆蓋了@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 網絡請求和錯誤處理是怎樣的,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。