自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我司是怎么封裝 Axios 來處理百萬級流量中平時少見過的問題

開發(fā) 前端
本文是我們團(tuán)隊每周分享的內(nèi)容,該內(nèi)容是由導(dǎo)師整理分享的。Eaxios 是我們前端團(tuán)隊自己在用的庫,由導(dǎo)師封裝的,因為其他小伙伴對它有所好奇,所以才有該篇的分享內(nèi)容。

[[416113]]

本文是我們團(tuán)隊每周分享的內(nèi)容,該內(nèi)容是由導(dǎo)師整理分享的。Eaxios 是我們前端團(tuán)隊自己在用的庫,由導(dǎo)師封裝的,因為其他小伙伴對它有所好奇,所以才有該篇的分享內(nèi)容。

正文開始~~

Eaxios

Eaxios 是基于 axios 封裝的網(wǎng)絡(luò)請求庫,在保持 API 與 axios 基本一致的情況下,簡化服務(wù)端響應(yīng)內(nèi)容和各種異常情況的處理。

開發(fā)背景

圖片

如上圖所示,是一次 Ajax 請求可能輸出的結(jié)果,在前端我們需要根據(jù)輸出結(jié)果給用戶不同的提示。

  • 請求被取消:忽略
  • 網(wǎng)絡(luò)異常:提示檢查是否連接網(wǎng)絡(luò)
  • 請求超時:提示網(wǎng)絡(luò)慢,請切換網(wǎng)絡(luò)
  • 服務(wù)器異常:提示系統(tǒng)出問題了
  • 響應(yīng)解析失?。和?,且可以進(jìn)行錯誤日志上報
  • 請求失?。哼@種情況通常是業(yè)務(wù)異常,前端需要根據(jù)錯誤碼進(jìn)行相應(yīng)的處理,最簡單的就是消息提醒
  • 請求成功:前端拿到數(shù)據(jù)后更新界面

但是,現(xiàn)有的 Axios 庫對于異常結(jié)果沒有提供較好的封裝,Axios Promise catch 里包含各種類型的錯誤,而且沒有提供錯誤碼來識別請求失敗的原因。而且很多服務(wù)端接口會返回自己的錯誤碼,這樣在 Axios Promise then 里也需要處理業(yè)務(wù)異常。

此外,Axios 本身如下所述的一些問題和局限性。

  • 如果設(shè)置 Axios responseType 為 json 時,服務(wù)端返回的非 JSON 格式的響應(yīng)內(nèi)容會因為無法解析,response.data 為 null

對于 500 等錯誤,響應(yīng)內(nèi)容會丟失,所以不要去配置 responseType 為 json,對于使用者來說容易采到這個坑。

ps:雖然 Axios 官方文檔聲明 responseType 是 json,實際上底層調(diào)用 XMLHttpRequest 的 responseType 是沒有傳值的,應(yīng)該是為了規(guī)避這個問題。

  • Axios 默認(rèn)不管 HTTP 響應(yīng)狀態(tài)和 responseType 是什么,都會調(diào)用默認(rèn)的 transformResponse

ps:應(yīng)該是為了規(guī)避上一個問題,默認(rèn)提供了一個響應(yīng)處理函數(shù)進(jìn)行 JSON 解析,但是這會影響性能(500 等響應(yīng)內(nèi)容值較多時,會造成頁面卡頓)。雖然 transformResponse 可以轉(zhuǎn)換 response,實際接收到的參數(shù)是 response.data,所以無法判斷具體情況來決定是否進(jìn)行解析 JSON。

  • Axios then 和 catch 是根據(jù) validateStatus 決定的,使用者處理以來較為麻煩。

理想情況下,使用者希望 then 返回有效的數(shù)據(jù),catch 返回各種錯誤情況:請求被取消、網(wǎng)絡(luò)異常、網(wǎng)絡(luò)超時、服務(wù)端異常、服務(wù)端數(shù)據(jù)格式錯誤、業(yè)務(wù)異常。

  • Axios 默認(rèn)不處理 content-type 為 application/x-www-form-urlencoded 類型的請求體,使用起來不夠方便

優(yōu)化方案:

  • 如果設(shè)置 Axios responseType 為 json 時,不要傳給傳 XMLHttpRequest,以避免非 JSON 格式的響應(yīng)內(nèi)容丟失
  • Axios 根據(jù)響應(yīng)頭的 content-type 判斷是否需要解析 JSON,以避免性能問題
  • 通過請求攔截器實現(xiàn)不給 Axios 傳遞 transformResponse 配置,且將配置備份到其他字段上,然后在響應(yīng)攔截器中將響應(yīng)對象 response 傳遞給 transformResponse 處理。響應(yīng)攔截器根據(jù) response 提供的狀態(tài)碼、響應(yīng)頭和響應(yīng)內(nèi)容判斷是否要進(jìn)行 JSON 轉(zhuǎn)換。
  • 取消 Axios validateStatus 的配置選項,默認(rèn)所有大于 0 的狀態(tài)碼都是正確的狀態(tài)碼,然后在 Axios 攔截器 then 中進(jìn)行數(shù)據(jù)解析(非 200 的可能也是 JSON,所以要復(fù)用 200 的 JSON 解析代碼),并且根據(jù)異常情況拋出直觀的錯誤對象
  • 內(nèi)置默認(rèn)處理表單類型的請求體

用法說明

eaxios 主要對響應(yīng)的處理做了一些優(yōu)化,除了以下部分,eaxios 的 api 與 axios 保持一致:

  • eaxios 請求配置的 transformResponse 傳參和處理時機發(fā)生了變化
  • axios 在服務(wù)端響應(yīng)內(nèi)容后就會調(diào)用 transformResponse 進(jìn)行響應(yīng)轉(zhuǎn)換,eaxios 響應(yīng)后內(nèi)部自動根據(jù)響應(yīng)頭和 responseType 進(jìn)行 JSON 解析,然后將解析后的數(shù)據(jù)和 response 傳給 transformResponse,transformResponse 返回的數(shù)據(jù)最終會被 Promise resovle 給外部調(diào)用者。
  • 假設(shè)服務(wù)端返回的數(shù)據(jù)結(jié)構(gòu)為 { code: 0, message: 'success', data: {} },code 為 0 表示正確的響應(yīng),非 0 表示異常,接口請求的代碼示例如下所示:
  1. const eaxios = require('eaxios'); 
  2.  
  3. eaxios.defaults.transformResponse = [ 
  4.   function (data, response) { 
  5.     if (typeof data === 'object') { 
  6.       // 默認(rèn)約定有成功解析 JSON 對象,就認(rèn)為服務(wù)端成功響應(yīng),且有提供錯誤碼 
  7.       if (data.code === 0) { 
  8.         return data.data; 
  9.       } else { 
  10.         throw eaxios.createError(data.message, data.code, response); 
  11.       } 
  12.     } else { 
  13.       // 50x 等服務(wù)異常情況 
  14.       throw eaxios.createError( 
  15.         data, 
  16.         response.config.responseError.SERVER_ERROR, 
  17.         response 
  18.       ); 
  19.     } 
  20.   }, 
  21. ]; 
  22.  
  23. return eaxios('https://run.mocky.io/v3/4f503449-0349-467e-a38a-c804956712b7'
  24.   .then((data) => { 
  25.     console.log('success', data.id); 
  26.   }) 
  27.   .catch((error) => { 
  28.     console.log('failure', error.code); // UNKNOWN、REQUEST_OFFLINE、REQUEST_TIMEOUT、SERVER_ERROR、RESPONSE_INVALID 和業(yè)務(wù)錯誤碼 
  29.   }); 

ps:如果存在服務(wù)單接口請求規(guī)范,可以通過 eaxios.create 創(chuàng)建適用于不同接口規(guī)范的請求函數(shù)。

  • eaxios 的請求處理函數(shù) then 只會接收到 transformResponse 轉(zhuǎn)換后的數(shù)據(jù),對于網(wǎng)絡(luò)、超時、服務(wù)端異常和業(yè)務(wù)異常等問題,會在 catch 接收一個 EaxiosError 類型的錯誤對象。

  1. interface EaxiosError<T = any> extends Error { 
  2.   config: EaxiosRequestConfig; 
  3.   code?: string; 
  4.   request?: any
  5.   response?: EaxiosResponse<T>; 
  6.   isAxiosError: boolean; 
  7.   toJSON: () => object; 

錯誤處理函數(shù)可以根據(jù)錯誤碼 code 來處理異常,code 可能的值為 UNKNOWN、REQUEST_OFFLINE、REQUEST_TIMEOUT、SERVER_ERROR、RESPONSE_INVALID 和其他業(yè)務(wù)錯誤碼。ps:如果要定制錯誤碼,可以在請求配置中添加配置項 `responseError`。

  1. eaxios.defaults.responseError = { 
  2.   REQUEST_OFFLINE: '1'REQUEST_OFFLINE 
  3. }; 
  • eaxios 內(nèi)部會自動序列化表單類型的請求參數(shù),所以主要傳對象給 data 就行了。

代碼示例

下面以 { code: 0, message: 'success', data: { } } 這樣的接口規(guī)范為例,演示如何使用 eaxios。

  1. const eaxios = require('..'); 
  2.  
  3. const request = eaxios.create({ 
  4.   baseURL: 'https://run.mocky.io/v3'
  5.   timeout: 30000, 
  6.   transformResponse: [ 
  7.     function (data, response) { 
  8.       if (typeof data === 'object') { 
  9.         if (data.code === 0) { 
  10.           return data.data; 
  11.         } else { 
  12.           throw eaxios.createError(data.message, data.code, response); 
  13.         } 
  14.       } else { 
  15.         throw eaxios.createError( 
  16.           data, 
  17.           response.config.responseError.SERVER_ERROR, 
  18.           response, 
  19.         ); 
  20.       } 
  21.     }, 
  22.   ], 
  23. }); 
  24.  
  25. request.interceptors.response.use( 
  26.   function (response) { 
  27.     return response; 
  28.   }, 
  29.   function (error) { 
  30.     if (error && error.code) { 
  31.       if (error.code === 'UNKNOWN') { 
  32.         console.log('未知錯誤'); 
  33.       } else if (error.code === 'REQUEST_OFFLINE') { 
  34.         console.log('網(wǎng)絡(luò)未連接'); 
  35.       } else if (error.code === 'REQUEST_TIMEOUT') { 
  36.         console.log('網(wǎng)絡(luò)有點慢,請求超時了'); 
  37.       } else if (error.code === 'SERVER_ERROR') { 
  38.         console.log('系統(tǒng)出問題了'); 
  39.       } else if (error.code === 'RESPONSE_INVALID') { 
  40.         console.log('服務(wù)端 bug'); 
  41.       } else if (error.code === '10000') { 
  42.         // 假設(shè) 10000 為登錄會話過期 
  43.         console.log('登錄會話失效'); 
  44.       } else { 
  45.         console.log('根據(jù)情況是否要消息提示,還是外部處理'
  46.       } 
  47.     } 
  48.     throw error; 
  49.   }, 
  50. ); 
  51.  
  52. function printError(error) { 
  53.   console.log( 
  54.     `code: ${error.code}, name: ${error.name}, message: ${error.message}, isAxiosError: ${error.isAxiosError}, stack:\n${error.stack}`, 
  55.   ); 
  56.  
  57. function success() { 
  58.   console.log('>> success'); 
  59.   return request('/4f503449-0349-467e-a38a-c804956712b7'
  60.     .then((data) => { 
  61.       console.log('success', data); 
  62.     }) 
  63.     .catch((error) => { 
  64.       printError(error); 
  65.     }); 
  66.  
  67. function failure() { 
  68.   console.log('>> failure'); 
  69.   return request('/42d7c21d-5ae6-4b52-9c2d-4c3dd221eba4'
  70.     .then((data) => { 
  71.       console.log('success', data); 
  72.     }) 
  73.     .catch((error) => { 
  74.       printError(error); 
  75.     }); 
  76.  
  77. function invalid() { 
  78.   console.log('>> invalid'); 
  79.   return request('/1b23549f-c918-4362-9ac8-35bc275c09f0'
  80.     .then((data) => { 
  81.       console.log('success', data); 
  82.     }) 
  83.     .catch((error) => { 
  84.       printError(error); 
  85.     }); 
  86.  
  87. function server_500() { 
  88.   console.log('>> server_500'); 
  89.   return request('/2a9d8c00-9688-4d36-b2de-2dee5e81f5b3'
  90.     .then((data) => { 
  91.       console.log('success', data); 
  92.     }) 
  93.     .catch((error) => { 
  94.       printError(error); 
  95.     }); 
  96.  
  97. success().then(failure).then(invalid).then(server_500); 
  98. /* log 
  99. >> success 
  100. success { id: 1 } 
  101. >> failure 
  102. 登錄會話失效 
  103. code: 10000, name: Error, message: error, isAxiosError: true, stack: ... 
  104. >> invalid 
  105. 服務(wù)端 bug 
  106. code: RESPONSE_INVALID, name: SyntaxError, message: Unexpected token V in JSON at position 0, isAxiosError: true, stack: ... 
  107. >> server_500 
  108. 系統(tǒng)出問題了 
  109. code: SERVER_ERROR, name: Error, message: ...,  stack: ... 
  110. */ 

兼容性

eaxios 依賴 URLSearchParams 處理表單類型的請求參數(shù),不支持的環(huán)境需要引入響應(yīng)的 polyfill

  • core-js
  1. require("core-js/modules/web.url-search-params.js"
  • url-search-params-polyfill

【編輯推薦】

 

責(zé)任編輯:姜華 來源: 大遷世界
相關(guān)推薦

2012-07-20 10:03:38

CSS

2021-03-31 10:12:12

MongoDBQPS存儲

2021-07-27 14:50:15

axiosHTTP前端

2011-08-23 17:12:22

MySQL支撐百萬級流

2018-06-22 08:13:21

2009-07-08 13:31:23

調(diào)用Servlet處理

2024-04-30 11:00:10

數(shù)據(jù)中心

2021-08-31 07:11:48

MySQL億級流量

2011-03-08 15:58:54

處理器能耗

2024-03-26 00:54:42

預(yù)測模型數(shù)據(jù)

2017-08-25 14:23:44

TensorFlow神經(jīng)網(wǎng)絡(luò)文本分類

2021-06-07 05:46:20

前端架構(gòu)前端架構(gòu)

2021-01-21 09:09:18

時區(qū)轉(zhuǎn)換程序

2019-04-08 20:20:37

2014-02-10 16:27:09

百萬級IOPSOceanStor 1

2025-02-28 10:10:48

2020-12-16 08:33:58

Excel數(shù)據(jù)分析FineBI

2021-02-02 10:53:16

Python編程開發(fā)

2022-10-19 11:17:35

2021-08-07 07:23:08

Webpack中間件模型
點贊
收藏

51CTO技術(shù)棧公眾號