前言:umi-request是react項目初始化時,封裝請求通用配置,很好用的基於fetch的請求庫, 結合和優化了fetch與axios的優點。
背景
在做中台業務應用開發的過程中,我們發現在請求鏈路上存在以下問題:
- 請求庫各式各樣,沒有統一。 每次新起應用都需要重復實現一套請求層邏輯,切換應用時需要重新學習請求庫 API。
- 各應用接口設計不一致、混亂。 前后端同學每次需重新設計接口格式,前端同學在切換應用時需重新了解接口格式才能做業務開發。
- 接口文檔維護各式各樣。 有的在語雀(雲端知識庫)上,有的在 RAP (開源接口管理工具)上,有的靠閱讀源碼才能知道,無論是維護、mock 數據還是溝通都很浪費人力。
針對以上問題,我們提出了請求層治理,希望能通過統一請求庫、規范請求接口設計規范、統一接口文檔這三步,對請求鏈路的前中后三個階段進行提效和規范, 從而減少開發者在接口設計、文檔維護、請求層邏輯開發上花費的溝通和人力成本。其中,統一請求庫作為底層技術支持,需要提前打好基地,為上層提供穩定、完善的功能支持,基於此,umi-request 應運而生。
umi-request
umi-request 是基於 fetch 封裝的開源 http 請求庫,旨在為開發者提供一個統一的 API 調用方式,同時簡化使用方式,提供了請求層常用的功能:
- URL 參數自動序列化
- POST 數據提交方式簡化
- Response 返回處理簡化
- 請求超時處理
- 請求緩存支持
- GBK 編碼處理
- 統一的錯誤處理方式
- 請求取消支持
- Node 環境 http 請求
- 攔截器機制
- 洋蔥中間件機制
與 fetch、axios 的異同?
umi-request 底層拋棄了設計粗糙、不符合關注分離的 XMLHttpRequest,選擇了更加語義化、基於標准 Promise 實現的 fetch(更多細節詳見);同時同構更方便,使用 isomorphic-fetch(目前已內置);而基於各業務應用場景提取常見的請求能力並支持快速配置如 post 簡化、前后綴、錯誤檢查等。
上手便捷
安裝
npm install --save umi-request
執行 GET 請求
import request from "umi-request"; request .get("/api/v1/xxx?id=1") .then(function(response) { console.log(response); }) .catch(function(error) { console.log(error); }); // 也可將 URL 的參數放到 options.params 里 request .get("/api/v1/xxx", { params: { id: 1 } }) .then(function(response) { console.log(response); }) .catch(function(error) { console.log(error); });
執行 POST 請求
import request from "umi-request"; request .post("/api/v1/user", { data: { name: "Mike" } }) .then(function(response) { console.log(response); }) .catch(function(error) { console.log(error); });
實例化通用配置
請求一般都有一些通用的配置,我們不想在每個請求里去逐個添加,例如通用的前綴、后綴、頭部信息、異常處理等等,那么可以通過 extend 來新建一個 umi-request 實例,從而減少重復的代碼量:
import { extend } from "umi-request"; const request = extend({ prefix: "/api/v1", suffix: ".json", timeout: 1000, headers: { "Content-Type": "multipart/form-data" }, params: { token: "xxx" // 所有請求默認帶上 token 參數 }, errorHandler: function(error) { /* 異常處理 */ } }); request .get("/user") .then(function(response) { console.log(response); }) .catch(function(error) { console.log(error); });
內置常見請求能力
fetch 本身並不提供請求超時、緩存、取消等能力,而在業務開發中卻常常需要,因此 umi-request 對常見的請求能力進行封裝內置,減少重復開發:
{ // 'params' 是即將於請求一起發送的 URL 參數,參數會自動 encode 后添加到 URL 中 // 類型需為 Object 對象或者 URLSearchParams 對象 params: { id: 1 }, // 'paramsSerializer' 開發者可通過該函數對 params 做序列化(注意:此時傳入的 params 為合並了 extends 中 params 參數的對象,如果傳入的是 URLSearchParams 對象會轉化為 Object 對象 paramsSerializer: function (params) { return Qs.stringify(params, { arrayFormat: 'brackets' }) }, // 'data' 作為請求主體被發送的數據 // 適用於這些請求方法 'PUT', 'POST', 和 'PATCH' // 必須是以下類型之一: // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams // - 瀏覽器專屬:FormData, File, Blob // - Node 專屬: Stream data: { name: 'Mike' }, // 'headers' 請求頭 headers: { 'Content-Type': 'multipart/form-data' }, // 'timeout' 指定請求超時的毫秒數(0 表示無超時時間) // 如果請求超過了 'timeout' 時間,請求將被中斷並拋出請求異常 timeout: 1000, // 'prefix' 前綴,統一設置 url 前綴 // ( e.g. request('/user/save', { prefix: '/api/v1' }) => request('/api/v1/user/save') ) prefix: '', // 'suffix' 后綴,統一設置 url 后綴 // ( e.g. request('/api/v1/user/save', { suffix: '.json'}) => request('/api/v1/user/save.json') ) suffix: '', // 'credentials' 發送帶憑據的請求 // 為了讓瀏覽器發送包含憑據的請求(即使是跨域源),需要設置 credentials: 'include' // 如果只想在請求URL與調用腳本位於同一起源處時發送憑據,請添加credentials: 'same-origin' // 要改為確保瀏覽器不在請求中包含憑據,請使用credentials: 'omit' credentials: 'same-origin', // default // 'useCache' 是否使用緩存,當值為 true 時,GET 請求在 ttl 毫秒內將被緩存,緩存策略唯一 key 為 url + params 組合 useCache: false, // default // 'ttl' 緩存時長(毫秒), 0 為不過期 ttl: 60000, // 'maxCache' 最大緩存數, 0 為無限制 maxCache: 0, // 'charset' 當服務端返回的數據編碼類型為 gbk 時可使用該參數,umi-request 會按 gbk 編碼做解析,避免得到亂碼, 默認為 utf8 // 當 parseResponse 值為 false 時該參數無效 charset: 'gbk', // 'responseType': 如何解析返回的數據,當 parseResponse 值為 false 時該參數無效 // 默認為 'json', 對返回結果進行 Response.text().then( d => JSON.parse(d) ) 解析 // 其他(text, blob, arrayBuffer, formData), 做 Response[responseType]() 解析 responseType: 'json', // default // 'errorHandler' 統一的異常處理,供開發者對請求發生的異常做統一處理,詳細使用請參考下方的錯誤處理文檔 errorHandler: function(error) { /* 異常處理 */ }, }
總結
隨着 umi-request 能力的完善,已經能夠支持各個場景、端應用的請求,前端開發只需要掌握一套 API 調用就能實現多端開發,再也不用關注底層協議實現,把更多的精力放在前端開發上。而基於此,umi-request 能在底層做更多的事情,如 mock 數據、自動識別請求類型、接口異常監控上報、接口規范校驗等等,最終實現請求治理的目標。umi-request 還有很多能力沒有在文中提及,如有興趣歡迎查看詳細文檔,如果你有好的建議和需求,也歡迎提 issue。
注:博客轉載自數據體驗技術知乎文章