umi-request
umi-request 是基於 fetch 的封裝,兼具 fetch 和 axios 的特點。旨在為開發者提供便捷統一的請求方式。Ant Pro 中對 其進行了初步的封裝。比如:統一的錯誤處理方式。
但是,在實際中我們可能會遇見各種各樣的情況,需要按照自己的需求對其進行封裝。那就首先從 Ant Pro 的統一的異常處理程序開始吧。
首先,引入umi-request的擴展到項目中。
import { extend } from 'umi-request';
其次,根據自己的項目實際情況定義錯誤碼和其對應的提示語。
const codeMessage = {
200: '服務器成功返回請求的數據。',
201: '新建或修改數據成功。',
202: '一個請求已經進入后台排隊(異步任務)。',
204: '刪除數據成功。',
400: '發出的請求有錯誤,服務器沒有進行新建或修改數據的操作。',
401: '用戶沒有權限(令牌、用戶名、密碼錯誤)。',
403: '用戶得到授權,但是訪問是被禁止的。',
404: '發出的請求針對的是不存在的記錄,服務器沒有進行操作。',
406: '請求的格式不可得。',
410: '請求的資源被永久刪除,且不會再得到的。',
422: '當創建一個對象時,發生一個驗證錯誤。',
500: '服務器發生錯誤,請檢查服務器。',
502: '網關錯誤。',
503: '服務不可用,服務器暫時過載或維護。',
504: '網關超時。',
};
然后,寫異常處理函數
/**
* 異常處理程序
*/
const errorHandler = (error: { response: Response }): Response => {
const { response } = error;
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const { status, url } = response;
notification.error({
message: `請求錯誤 ${status}: ${url}`,
description: errorText,
});
} else if (!response) {
notification.error({
description: '您的網絡發生異常,無法連接服務器',
message: '網絡異常',
});
}
return response;
};
/**
* 配置request請求時的默認參數
*/
const request = extend({
errorHandler, // 默認錯誤處理
credentials: 'include', // 默認請求是否帶上cookie
// timeout: 60000, // 請求超時
});
首先第一個需求:對請求結果異常的統一處理。比如:token 失效時,應該統一彈框提示,並且跳回到登錄頁。非成功的統一提示。直接拿到后端返回的數據而去掉外層的包裝。
request.interceptors.response.use(async (response) => {
const data = await response.clone().json();
// const currentInterface = getPureInterface(response.url); // 這個方法是為了得到純接口,然后可以適時的選擇跳過,或者做別的操作
// token 失效
if(data.code === 1014) {
window.location.href = `${window.location.origin}/user/login`;
}
// 統一報錯信息。需特殊跳過的接口可以在這里跳過
if(data.code === 1009) {
// ant 引入的組件
notification.error({
message: '請求錯誤',
description: data.message,
})
}
return response;
})
比如后端接口不同類型需要的參數格式不同。
// get 請求,參數拼接在 url 后面。並且需要在 headers 里面添加參數 token
const requestGet = (url: string, data?: object) => {
return request.get(`${url}?${qs.stringify({ ...data, t: Date.now() })}`, {
headers: {
tokenId: getCookie("token"),
}
})
}
// post 請求,form 格式,每個請求都需要包含 token,accout 參數
const requestPost = (url: string, data?: object) => {
return request.post(url, {
method: 'POST',
data: {
...data,
tokenId: getCookie("token"),
account: getCookie("account"),
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
tokenId: getCookie("token"),
}
})
}
// post 請求,要求的入參卻是 json 格式
const requestPostJson = (url: string, data?: object) => {
return request.post(url, {
method: 'POST',
data,
headers: {
'Content-Type': 'application/json',
tokenId: getCookie("token"),
},
})
}
// 這是全局的攔截,還可以寫局部的攔截器
封裝完成之后,最后暴露出來即可使用
export default {
get: requestGet,
post: requestPost,
json: requestPostJson
};
比如請求前的攔截
/**
* 請求前攔截。比如添加數據或者,修改url
*/
request.interceptors.request.use( (url, options) => {
// console.log('url=',url)
// console.log('options', options)
/**
* 這里的添加會在上面各自的請求之后執行,比如url 的拼接
* 這里可以根據 options 的參數決定要不要修改或者拼接不同的前后綴
* options 包含 credentials、errorHandler、headers、method、params、
*/
return {
url: `xingquan${url}&author=guozheng`,
options: {...options, interceptors: true}
}
})
還有好多方便的用法,文檔很詳細,使用到再補充。