axios的interceptors多次執(zhí)行問題解決
問題
在進行 axios 封裝的時候,遇到個問題,就是每次發(fā)起請求時axios 都會執(zhí)行兩次響應攔截,甚是納悶,一時理不出思路來。
代碼如下:
class Http {
constructor(config) {
this.axios = axios;
this.axiosInterceptor = undefined;
// 公共的 header
let defaultHeaders = {
'Content-Type': 'application/json;charset=UTF-8',
'Accept': 'application/json', // 通過頭指定,獲取的數(shù)據(jù)類型是JSON 'application/json, text/plain, */*',
'x-end-point': '.10.'
}
if(config?.headers){
for (let i in config.headers) {
defaultHeaders[i] = config.headers[i];
}
}
axios({
// `baseURL` 將自動加在 `url` 前面,除非 `url` 是一個絕對 URL。
// 它可以通過設置一個 `baseURL` 便于為 axios 實例的方法傳遞相對 URL
baseURL: config?.baseURL,
// `url` 是用于請求的服務器 URL
url: config?.url,
// `method` 是創(chuàng)建請求時使用的方法
method: config?.method || 'get',
// `headers` 是即將被發(fā)送的自定義請求頭
headers: {...defaultHeaders},
// `params` 是即將與請求一起發(fā)送的 URL 參數(shù)
// 必須是一個無格式對象(plain object)或 URLSearchParams 對象
params: config?.method === 'get' ? config?.params || {} : {},
// `paramsSerializer` 是一個負責 `params` 序列化的函數(shù)
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function(params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// `data` 是作為請求主體被發(fā)送的數(shù)據(jù)
// 只適用于這些請求方法 'PUT', 'POST', 和 'PATCH'
// 在沒有設置 `transformRequest` 時,必須是以下類型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 瀏覽器專屬:FormData, File, Blob
// - Node 專屬: Stream
data: config?.method === 'post' ? config?.params || {} : {},
// `timeout` 指定請求超時的毫秒數(shù)(0 表示無超時時間)
// 如果請求話費了超過 `timeout` 的時間,請求將被中斷
timeout: 0,
// `withCredentials` 表示跨域請求時是否需要使用憑證
withCredentials: false, // default 為true則產(chǎn)生跨域,跨域攜帶cookie
// `responseType` 表示服務器響應的數(shù)據(jù)類型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // default
});
// 添加請求攔截器
axios.interceptors.request.use( (config) => {
// 在發(fā)送請求之前做些什么
return config;
}, function (error) {
// 對請求錯誤做些什么
return Promise.reject(error);
});
// 添加響應攔截器
axios.interceptors.response.use((res) => {
const { status, data } = res;
// 對錯誤狀態(tài)提示進行處理
let message = ''
if (status < 200 || status >= 300) {
// 處理http錯誤,拋到業(yè)務代碼
message = this.showResState(status)
if (typeof res.data === 'string') {
res.data = {code:status, message }
} else {
res.data.code = status
res.data.message = message
}
}
return res.data;
}, function (error) {
// 對響應錯誤做點什么
return Promise.reject(error);
});
}
get(url,params={}){
// 為給定 ID 的 user 創(chuàng)建請求
return new Promise((resolve, reject) => {
this.axios.get(url,{
params
}).then(response => {
// 2. 如果成功了, 調用resolve(value)
resolve(response);
})
.catch(error => {
// 3. 如果失敗了, 不調用reject(reason), 而是提示異常信息
reject(error)
// message.error('請求出錯了: ' + error.message).then(r => {});
}).finally(() => {
})
});
}
post(url,params={}){
return new Promise((resolve, reject) => {
this.axios.post(url, params).then(response => {
// 2. 如果成功了, 調用resolve(value)
resolve(response);
})
.catch(error => {
// 3. 如果失敗了, 不調用reject(reason), 而是提示異常信息
reject(error)
// message.error('請求出錯了: ' + error.message).then(r => {});
}).finally(() => {
})
});
}
showResState (state) {
let message = '';
// 這里只做部分常見的示例,具體根據(jù)需要進行配置
switch (state) {
case 400:
message = '請求錯誤(400)'
break
case 401:
message = '未授權,請重新登錄(401)'
break
case 403:
message = '拒絕訪問(403)'
break
case 404:
message = '請求出錯(404)'
break
case 500:
message = '服務器錯誤(500)'
break
case 501:
message = '服務未實現(xiàn)(501)'
break
case 502:
message = '網(wǎng)絡錯誤(502)'
break
case 503:
message = '服務不可用(503)'
break
default:
message = `連接出錯(${state})!`
}
return `${message},請檢查網(wǎng)絡或聯(lián)系網(wǎng)站管理員!`
}
// 插件初始化時會傳入所需的配置項
autoAddToken (config) {
// 在請求階段時修改 config 配置項為其添加 token 具體屬性名稱可自定義
config.headers ??= {}
config.headers.Authorization = localStorage.token || null
return config
}
}
export default Http;
可能遇到過該類問題的小伙伴們一眼就看出問題所在,對于未有碰到過這個問題的小伙伴,可能就又點煎熬了。
原因
若你使用use,就像Node.js里的use那樣,會不斷地往axios對象添加interceptors,由于我將該攔截器放在函數(shù)內,只要函數(shù)被執(zhí)行,則會再次將攔截器函數(shù)增添到axios對象上。
所以,推薦的辦法是,將攔截器放在函數(shù)外,可我的需求決定了,我必須將它放在函數(shù)內,那么該如何解決呢?
解決
添加該文件內的唯一變量標識符let interceptor = null,進行判斷,只要攔截器存在,則不會繼續(xù)添加,部分代碼如下所示:
if (!this.interceptor) {
// 添加響應攔截器
this.interceptor = axios.interceptors.response.use((res) => {
const { status, data } = res;
// 對錯誤狀態(tài)提示進行處理
let message = ''
if (status < 200 || status >= 300) {
// 處理http錯誤,拋到業(yè)務代碼
message = this.showResState(status)
if (typeof res.data === 'string') {
res.data = {code:status, message }
} else {
res.data.code = status
res.data.message = message
}
}
return res.data;
}, function (error) {
// 對響應錯誤做點什么
return Promise.reject(error);
});
}
奈何不好使。不得一不得不把攔截器提取到類外部,問題解決。
這里只貼部分主要代碼:
import axios from "axios";
/* 將攔截器 置于封裝類之外 */
// 添加請求攔截器
axios.interceptors.request.use( (config) => {
// 在發(fā)送請求之前做些什么 添加 token 等鑒權功能
//...
return config;
}, function (error) {
// 對請求錯誤做些什么
return Promise.reject(error);
});
// 添加響應攔截器
axios.interceptors.response.use((res) => {
const { status } = res;
// 在發(fā)送結果之前做些什么 對錯誤狀態(tài)提示進行處理
//...
return res.data;
}, function (error) {
// 對響應錯誤做點什么
return Promise.reject(error);
});
class Http {
constructor(config) {
this.axios = axios;
// 這里仍需對配置進行處理,代碼省略了
this.config = config;
}
// Get 請求
get(url,params={},headers={}){
// ...
}
// POST 請求
post(url,params={},headers={}){
// ...
}
}
export default Http;
// 無特殊需求的只需使用這個一個對象即可 公共 header 可在此配置, 如需多個實例 可按照此方式創(chuàng)建多個進行導出
export const Axios = new Http({
headers: {
'x-http-token': 'xxx'
}
});
這里不對具體的方法進行描述,只做一個解決問題的說明,后續(xù)會針對 axios 類的封裝,單獨寫篇文章再詳細說明下的
以上就是axios的interceptors多次執(zhí)行問題解決的詳細內容,更多關于axios interceptors多次執(zhí)行的資料請關注腳本之家其它相關文章!
相關文章
詳解vue中的父子傳值雙向綁定及數(shù)據(jù)更新問題
這篇文章主要介紹了vue中的父子傳值雙向綁定及數(shù)據(jù)更新問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-06-06
vue自定義鍵盤信息、監(jiān)聽數(shù)據(jù)變化的方法示例【基于vm.$watch】
這篇文章主要介紹了vue自定義鍵盤信息、監(jiān)聽數(shù)據(jù)變化的方法,結合實例形式分析了vue.js基于vm.$watch進行事件監(jiān)聽相關操作技巧,需要的朋友可以參考下2019-03-03
VUE使用echarts?5.0以上版本渲染器未導入錯誤問題
這篇文章主要介紹了VUE使用echarts?5.0以上版本渲染器未導入錯誤問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
第一次在Vue中完整使用AJAX請求和axios.js的實戰(zhàn)記錄
AJAX是現(xiàn)代Web開發(fā)的一個關鍵部分,盡管它一開始看起來令人生畏,但在你的武庫中擁有它是必須的,下面這篇文章主要給大家介紹了關于第一次在Vue中完整使用AJAX請求和axios.js的相關資料,需要的朋友可以參考下2022-11-11

