掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
本文是我們團(tuán)隊(duì)每周分享的內(nèi)容,該內(nèi)容是由導(dǎo)師整理分享的。Eaxios 是我們前端團(tuán)隊(duì)自己在用的庫,由導(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è)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
正文開始~~
Eaxios 是基于 axios 封裝的網(wǎng)絡(luò)請(qǐng)求庫,在保持 API 與 axios 基本一致的情況下,簡(jiǎn)化服務(wù)端響應(yīng)內(nèi)容和各種異常情況的處理。
如上圖所示,是一次 Ajax 請(qǐng)求可能輸出的結(jié)果,在前端我們需要根據(jù)輸出結(jié)果給用戶不同的提示。
但是,現(xiàn)有的 Axios 庫對(duì)于異常結(jié)果沒有提供較好的封裝,Axios Promise catch 里包含各種類型的錯(cuò)誤,而且沒有提供錯(cuò)誤碼來識(shí)別請(qǐng)求失敗的原因。而且很多服務(wù)端接口會(huì)返回自己的錯(cuò)誤碼,這樣在 Axios Promise then 里也需要處理業(yè)務(wù)異常。
此外,Axios 本身如下所述的一些問題和局限性。
對(duì)于 500 等錯(cuò)誤,響應(yīng)內(nèi)容會(huì)丟失,所以不要去配置 responseType 為 json,對(duì)于使用者來說容易采到這個(gè)坑。
ps:雖然 Axios 官方文檔聲明 responseType 是 json,實(shí)際上底層調(diào)用 XMLHttpRequest 的 responseType 是沒有傳值的,應(yīng)該是為了規(guī)避這個(gè)問題。
ps:應(yīng)該是為了規(guī)避上一個(gè)問題,默認(rèn)提供了一個(gè)響應(yīng)處理函數(shù)進(jìn)行 JSON 解析,但是這會(huì)影響性能(500 等響應(yīng)內(nèi)容值較多時(shí),會(huì)造成頁面卡頓)。雖然 transformResponse 可以轉(zhuǎn)換 response,實(shí)際接收到的參數(shù)是 response.data,所以無法判斷具體情況來決定是否進(jìn)行解析 JSON。
理想情況下,使用者希望 then 返回有效的數(shù)據(jù),catch 返回各種錯(cuò)誤情況:請(qǐng)求被取消、網(wǎng)絡(luò)異常、網(wǎng)絡(luò)超時(shí)、服務(wù)端異常、服務(wù)端數(shù)據(jù)格式錯(cuò)誤、業(yè)務(wù)異常。
優(yōu)化方案:
eaxios 主要對(duì)響應(yīng)的處理做了一些優(yōu)化,除了以下部分,eaxios 的 api 與 axios 保持一致:
- const eaxios = require('eaxios');
- eaxios.defaults.transformResponse = [
- function (data, response) {
- if (typeof data === 'object') {
- // 默認(rèn)約定有成功解析 JSON 對(duì)象,就認(rèn)為服務(wù)端成功響應(yīng),且有提供錯(cuò)誤碼
- if (data.code === 0) {
- return data.data;
- } else {
- throw eaxios.createError(data.message, data.code, response);
- }
- } else {
- // 50x 等服務(wù)異常情況
- throw eaxios.createError(
- data,
- response.config.responseError.SERVER_ERROR,
- response
- );
- }
- },
- ];
- return eaxios('https://run.mocky.io/v3/4f503449-0349-467e-a38a-c804956712b7')
- .then((data) => {
- console.log('success', data.id);
- })
- .catch((error) => {
- console.log('failure', error.code); // UNKNOWN、REQUEST_OFFLINE、REQUEST_TIMEOUT、SERVER_ERROR、RESPONSE_INVALID 和業(yè)務(wù)錯(cuò)誤碼
- });
ps:如果存在服務(wù)單接口請(qǐng)求規(guī)范,可以通過 eaxios.create 創(chuàng)建適用于不同接口規(guī)范的請(qǐng)求函數(shù)。
- interface EaxiosError
extends Error { - config: EaxiosRequestConfig;
- code?: string;
- request?: any;
- response?: EaxiosResponse
; - isAxiosError: boolean;
- toJSON: () => object;
- }
錯(cuò)誤處理函數(shù)可以根據(jù)錯(cuò)誤碼 code 來處理異常,code 可能的值為 UNKNOWN、REQUEST_OFFLINE、REQUEST_TIMEOUT、SERVER_ERROR、RESPONSE_INVALID 和其他業(yè)務(wù)錯(cuò)誤碼。ps:如果要定制錯(cuò)誤碼,可以在請(qǐng)求配置中添加配置項(xiàng) `responseError`。
- eaxios.defaults.responseError = {
- REQUEST_OFFLINE: '1'REQUEST_OFFLINE
- };
下面以 { code: 0, message: 'success', data: { } } 這樣的接口規(guī)范為例,演示如何使用 eaxios。
- const eaxios = require('..');
- const request = eaxios.create({
- baseURL: 'https://run.mocky.io/v3',
- timeout: 30000,
- transformResponse: [
- function (data, response) {
- if (typeof data === 'object') {
- if (data.code === 0) {
- return data.data;
- } else {
- throw eaxios.createError(data.message, data.code, response);
- }
- } else {
- throw eaxios.createError(
- data,
- response.config.responseError.SERVER_ERROR,
- response,
- );
- }
- },
- ],
- });
- request.interceptors.response.use(
- function (response) {
- return response;
- },
- function (error) {
- if (error && error.code) {
- if (error.code === 'UNKNOWN') {
- console.log('未知錯(cuò)誤');
- } else if (error.code === 'REQUEST_OFFLINE') {
- console.log('網(wǎng)絡(luò)未連接');
- } else if (error.code === 'REQUEST_TIMEOUT') {
- console.log('網(wǎng)絡(luò)有點(diǎn)慢,請(qǐng)求超時(shí)了');
- } else if (error.code === 'SERVER_ERROR') {
- console.log('系統(tǒng)出問題了');
- } else if (error.code === 'RESPONSE_INVALID') {
- console.log('服務(wù)端 bug');
- } else if (error.code === '10000') {
- // 假設(shè) 10000 為登錄會(huì)話過期
- console.log('登錄會(huì)話失效');
- } else {
- console.log('根據(jù)情況是否要消息提示,還是外部處理')
- }
- }
- throw error;
- },
- );
- function printError(error) {
- console.log(
- `code: ${error.code}, name: ${error.name}, message: ${error.message}, isAxiosError: ${error.isAxiosError}, stack:\n${error.stack}`,
- );
- }
- function success() {
- console.log('>> success');
- return request('/4f503449-0349-467e-a38a-c804956712b7')
- .then((data) => {
- console.log('success', data);
- })
- .catch((error) => {
- printError(error);
- });
- }
- function failure() {
- console.log('>> failure');
- return request('/42d7c21d-5ae6-4b52-9c2d-4c3dd221eba4')
- .then((data) => {
- console.log('success', data);
- })
- .catch((error) => {
- printError(error);
- });
- }
- function invalid() {
- console.log('>> invalid');
- return request('/1b23549f-c918-4362-9ac8-35bc275c09f0')
- .then((data) => {
- console.log('success', data);
- })
- .catch((error) => {
- printError(error);
- });
- }
- function server_500() {
- console.log('>> server_500');
- return request('/2a9d8c00-9688-4d36-b2de-2dee5e81f5b3')
- .then((data) => {
- console.log('success', data);
- })
- .catch((error) => {
- printError(error);
- });
- }
- success().then(failure).then(invalid).then(server_500);
- /* log
- >> success
- success { id: 1 }
- >> failure
- 登錄會(huì)話失效
- code: 10000, name: Error, message: error, isAxiosError: true, stack: ...
- >> invalid
- 服務(wù)端 bug
- code: RESPONSE_INVALID, name: SyntaxError, message: Unexpected token V in JSON at position 0, isAxiosError: true, stack: ...
- >> server_500
- 系統(tǒng)出問題了
- code: SERVER_ERROR, name: Error, message: ..., stack: ...
- */
eaxios 依賴 URLSearchParams 處理表單類型的請(qǐng)求參數(shù),不支持的環(huán)境需要引入響應(yīng)的 polyfill
- require("core-js/modules/web.url-search-params.js")
網(wǎng)頁題目:我司是怎么封裝Axios來處理百萬級(jí)流量中平時(shí)少見過的問題
網(wǎng)站地址:http://uogjgqi.cn/article/djsjoee.html

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流