vue+axois 封裝請求+攔截器(請求鎖+統一處理錯誤碼)
阿新 • • 發佈:2020-12-15
需求
- 封裝常用請求
- 攔截器-請求鎖
- 統一處理錯誤碼
一、封裝常用的請求
解決痛點:不要每一個模組的api都還要寫get,post,patch請求方法。直接將這些常用的方法封裝好。
解決方案:寫一個類,封裝好常用的請求
部分原始碼如下
export default class PublicAPI { constructor(url) { this.url = url; } get(params, filter) { if (Array.isArray(params)) { filter = typeof filter === 'object' ? JSON.stringify(filter) : filter; let qs = filter ? '?filter=' + filter : ''; return axios.get(this.url + '/' + params.join('/') + qs); } params = params || {}; return axios.get(this.url, { params }); } delete(id) { return axios.delete(`${this.url}/${id}`); } post(params) { return axios.post(this.url, params); }//常用請求 都可以封裝在這裡 }
二、攔截器-請求鎖
解決痛點:限制同一時間發多個同一個請求
解決方案:利用axios的攔截器 + axios.CancelToken,限制同一個請求多次傳送
原始碼如下
方案一:簡單款
let pending = []; //宣告一個數組用於儲存每個ajax請求的取消函式和ajax標識 let CancelToken = axios.CancelToken; let removePending = (config) => { for(let p in pending){ if(pending[p].u === config.url + '&' + config.method) { //當前請求在陣列中存在時執行函式體 pending[p].f(); //執行取消操作 pending.splice(p, 1); //把這條記錄從陣列中移除 } } }
方案二:複雜款(這個是在掘金上看到的,原連結找不到了)
let pending = {}; /** * cancelKey管理器 * * @return {Object} 返回一個物件,物件暴露兩個方法,一個可以獲取本次請求的key,一個是設定本次請求的key * @memberof HttpRequest */ let cancelKeyManager = () => { const expose = {}; expose.setKey = function setKey(config) { const { method, url, params, data } = config; expose.key = `${method}|${url}`; //expose.key = method === 'get' ? `${expose.key}&${JSON.stringify(params)}` : `${expose.key}&${JSON.stringify(data||{})}`; }; expose.getKey = function getKey() { return expose.key; }; return expose; }; /** *處理請求攔截和請求取消 * * @param {object} config axios配置物件 * @param {boolean} [isCancel=true] 標識是請求取消還是攔截請求 * @return {object} 返回axios配置物件 * @memberof HttpRequest */ let handleRequestCancel = (config, isCancel = false) => { // 設定本次請求的key const { setKey, getKey } = cancelKeyManager(); setKey(config); const key = getKey(); const CancelToken = axios.CancelToken; // 取消已經發出去的請求 if (isCancel) { removeRequest(key, true); // 設定本次請求的cancelToken config.cancelToken = new CancelToken(c => { pending[key] = c; }); } else { // 攔截本次請求 config.cancelToken = new CancelToken(c => { // 將本次的cancel函式傳進去 pending[key] = c; removeRequest(key, true, c); }); } return config; }; /** * 移除請求 * * @param {string} key 標識請求的key * @param {boolean} [isRequest=false] 標識當前函式在請求攔截器呼叫還是響應攔截器呼叫 * @param {function} c cancel函式 * @memberof HttpRequest */ let removeRequest = (key, isRequest = false, c) =>{ // 請求前先判斷當前請求是否在pending中,如果存在有兩種情況: // 1. 上次請求還未響應,本次的請求被判為重複請求,則呼叫cancel方法攔截本次重複請求或者取消上一個請求 // 2. 上次請求已經響應,在response中被呼叫,清除key console.log(key,pending); if (pending[key]) { if (isRequest) { Message.error({ message: '請求過於頻繁' }); } else { // 上一次請求在成功響應後呼叫cancel函式刪除key delete pending[key]; } } };
三、統一處理錯誤碼
解決痛點:每個請求都需要處理錯誤資訊,特別是一些常用的錯誤(堅持能封裝就封裝的思想),當然具體業務處理邏輯這是各自處理啦!
解決方案:用axios攔截器,將返回來的錯誤統一處理,最常用的就是401 token失效吧!一般是要前後端統一錯誤碼的,固定的錯誤碼做固定的事情!
部分原始碼如下(感覺只適合部分)
axios.interceptors.response.use(
response => {
return new Promise((resolve, reject) => { //很重要 用promise 接收自定義錯誤碼
let data = response.data;
if (data.code === 'ok') {
return resolve({
data: data.data || data || {},
response: response
});
} else {
switch (data.code) {
case '10500': //自定義code
reject({
response: {
code: '10500',
status: 500,
msg: data.msg
}
});
break;
default:
reject(response);
}
}
});
},error => {}
)
總結
給出的原始碼比較分散,僅提供思路。
在專案中這麼一套全家桶用下來,十分巴適~~~
有疑問可以給我留言,我會盡力解答哦