日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
我司是怎么封裝Axios來(lái)處理百萬(wàn)級(jí)流量中平時(shí)少見(jiàn)過(guò)的問(wèn)題

本文是我們團(tuán)隊(duì)每周分享的內(nèi)容,該內(nèi)容是由導(dǎo)師整理分享的。Eaxios 是我們前端團(tuán)隊(duì)自己在用的庫(kù),由導(dǎo)師封裝的,因?yàn)槠渌』锇閷?duì)它有所好奇,所以才有該篇的分享內(nèi)容。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)東營(yíng)區(qū)免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

正文開(kāi)始~~

Eaxios

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

開(kāi)發(fā)背景

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

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

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

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

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

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

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

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

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

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

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

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

優(yōu)化方案:

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

用法說(shuō)明

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

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

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

  • eaxios 的請(qǐng)求處理函數(shù) then 只會(huì)接收到 transformResponse 轉(zhuǎn)換后的數(shù)據(jù),對(duì)于網(wǎng)絡(luò)、超時(shí)、服務(wù)端異常和業(yè)務(wù)異常等問(wèn)題,會(huì)在 catch 接收一個(gè) EaxiosError 類型的錯(cuò)誤對(duì)象。
 
 
 
 
  1. interface EaxiosError extends Error {
  2.   config: EaxiosRequestConfig;
  3.   code?: string;
  4.   request?: any;
  5.   response?: EaxiosResponse;
  6.   isAxiosError: boolean;
  7.   toJSON: () => object;
  8. }

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

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

代碼示例

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

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

兼容性

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

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


本文題目:我司是怎么封裝Axios來(lái)處理百萬(wàn)級(jí)流量中平時(shí)少見(jiàn)過(guò)的問(wèn)題
URL標(biāo)題:http://www.dlmjj.cn/article/djsjoee.html