前言: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。
注:博客轉載自數據體驗技術知乎文章
