本文是我們團隊每周分享的内容,該内容是由導師整理分享的。Eaxios 是我們前端團隊自己在用的庫,由導師封裝的,因為其他小夥伴對它有所好奇,所以才有該篇的分享内容。
正文開始~~
EaxiosEaxios 是基于 axios 封裝的網絡請求庫,在保持 API 與 axios 基本一緻的情況下,簡化服務端響應内容和各種異常情況的處理。
開發背景
如上圖所示,是一次 Ajax 請求可能輸出的結果,在前端我們需要根據輸出結果給用戶不同的提示。
但是,現有的 Axios 庫對于異常結果沒有提供較好的封裝,Axios Promise catch 裡包含各種類型的錯誤,而且沒有提供錯誤碼來識别請求失敗的原因。而且很多服務端接口會返回自己的錯誤碼,這樣在 Axios Promise then 裡也需要處理業務異常。
此外,Axios 本身如下所述的一些問題和局限性。
優化方案:
eaxios 主要對響應的處理做了一些優化,除了以下部分,eaxios 的 api 與 axios 保持一緻:
const eaxios = require('eaxios');
eaxios.defaults.transformResponse = [
function (data, response) {
if (typeof data === 'object') {
// 默認約定有成功解析 JSON 對象,就認為服務端成功響應,且有提供錯誤碼
if (data.code === 0) {
return data.data;
} else {
throw eaxios.createError(data.message, data.code, response);
}
} else {
// 50x 等服務異常情況
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 和業務錯誤碼
});
ps:如果存在服務單接口請求規範,可以通過 eaxios.create 創建适用于不同接口規範的請求函數。
interface EaxiosError<T = any> extends Error {
config: EaxiosRequestConfig;
code?: string;
request?: any;
response?: EaxiosResponse<T>;
isAxiosError: boolean;
toJSON: () => object;
}
錯誤處理函數可以根據錯誤碼 code 來處理異常,code 可能的值為 UNKNOWN、REQUEST_OFFLINE、REQUEST_TIMEOUT、SERVER_ERROR、RESPONSE_INVALID 和其他業務錯誤碼。
ps:如果要定制錯誤碼,可以在請求配置中添加配置項 `responseError`。
eaxios.defaults.responseError = {
REQUEST_OFFLINE: '1'REQUEST_OFFLINE
};
下面以 { code: 0, message: 'success', data: { } } 這樣的接口規範為例,演示如何使用 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('未知錯誤');
} else if (error.code === 'REQUEST_OFFLINE') {
console.log('網絡未連接');
} else if (error.code === 'REQUEST_TIMEOUT') {
console.log('網絡有點慢,請求超時了');
} else if (error.code === 'SERVER_ERROR') {
console.log('系統出問題了');
} else if (error.code === 'RESPONSE_INVALID') {
console.log('服務端 bug');
} else if (error.code === '10000') {
// 假設 10000 為登錄會話過期
console.log('登錄會話失效');
} else {
console.log('根據情況是否要消息提示,還是外部處理')
}
}
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
登錄會話失效
code: 10000, name: Error, message: error, isAxiosError: true, stack: ...
>> invalid
服務端 bug
code: RESPONSE_INVALID, name: SyntaxError, message: Unexpected token V in JSON at position 0, isAxiosError: true, stack: ...
>> server_500
系統出問題了
code: SERVER_ERROR, name: Error, message: ..., stack: ...
*/
eaxios 依賴 URLSearchParams 處理表單類型的請求參數,不支持的環境需要引入響應的 polyfill
require("core-js/modules/web.url-search-params.js")
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!