axios介紹
什么是axios
axios是一個基于Promise的HTTP庫划纽,可以用在瀏覽器或node.js中。
axios特點(diǎn):
- 從瀏覽器中創(chuàng)建XMLHTTPRequest
- 從node.js端創(chuàng)建http請求
- 支持PromiseAPI
- 攔截請求和響應(yīng)
- 轉(zhuǎn)換請求數(shù)據(jù)和響應(yīng)數(shù)據(jù)
- 取消請求
- 自動轉(zhuǎn)換JSON數(shù)據(jù)
- 客戶端支持防御XSRF
axios攔截器
為什么使用攔截器
頁面發(fā)送http請求疼约,很多情況我們要對請求和其響應(yīng)進(jìn)行特定的處理;例如每個請求都附帶后端返回的token,拿到response之前l(fā)oading動畫的展示等速妖。如果請求數(shù)非常多虱颗,這樣處理起來會非常的麻煩沥匈,程序的優(yōu)雅性也會大打折扣。在這種情況下忘渔,axios為開發(fā)者提供了這樣一個API:攔截器高帖。攔截器分為 請求(request)攔截器和 響應(yīng)(response)攔截器。
- 在請求和響應(yīng)被then或catch處理前攔截它們畦粮。
//添加請求攔截器
axios.interceptors.request.use(function(config){
//在請求發(fā)送之前做些什么
return config
},function(error){
//對請求錯誤做些什么
return Promise.reject(error)
})
//添加響應(yīng)請求
axios.interceptors.reponse.use(function(reponse){
//對響應(yīng)數(shù)據(jù)做些什么
return reponse
},function(error){
//對響應(yīng)錯誤做些什么
return Promise.reject(error)
})
- 添加攔截器使用
use
- 移除攔截器使用
eject
var myInterceptors = axios.interceptors.request.use()
//移除攔截器
axios.interceptors.request.eject(myInterceptors)
- axios自定義實(shí)例添加攔截器
//自定義實(shí)例
var instance = axios.create()
//添加攔截器
instance.interceptors.request.use()
axios取消請求
- 使用
cancel token
取消請求 - 可以使用 CancelToken.source 工廠方法創(chuàng)建 cancel token散址,
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 處理錯誤
}
});
// 取消請求(message 參數(shù)是可選的)
source.cancel('Operation canceled by the user.');
- 還可以通過傳遞一個 executor 函數(shù)到 CancelToken 的構(gòu)造函數(shù)來創(chuàng)建 cancel token:
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函數(shù)接收一個 cancel 函數(shù)作為參數(shù)
cancel = c;
})
});
// 取消請求
cancel();
借助axios的攔截器實(shí)現(xiàn)Vue.js中登陸狀態(tài)校驗(yàn)
后臺系統(tǒng)中乖阵,不是每個頁面都需要登錄權(quán)限,所以要對需要進(jìn)行登錄權(quán)限的頁面做好標(biāo)記预麸,使用路由的meta標(biāo)簽
{
path: '/userInfo',
name: '/userInfo',
meta: {
requireAuth: true // 該路由需要登錄權(quán)限校驗(yàn)
},
component: userInfo
},{
path: '/userInfo',
name: '/userInfo',
// 該路由需要登錄權(quán)限校驗(yàn)
component: userInfo
}
定義一起全局前置守衛(wèi)瞪浸,每次跳轉(zhuǎn)路由,進(jìn)行權(quán)限校驗(yàn)
router.beforeEach((to,from,next) => {
if(to.meta.requireAuth){ //如果路由需要校驗(yàn)權(quán)限
/*
從vuex拿出token碼吏祸,說明已經(jīng)登錄
(前端的Token可以偽造,并不靠譜)
*/
if(store.state.token){
next() //正常跳轉(zhuǎn)頁面
}else{
next({
path: "/login",
query: {redirect: to.fullPath}
/*將跳轉(zhuǎn)的路由地址作為參數(shù)帶給登錄頁对蒲,登錄成功后跳轉(zhuǎn)回改頁面 */
})
}
}else {
//如果不要校驗(yàn),直接進(jìn)入登錄頁
next()
}
})
但以上的實(shí)現(xiàn)存在問題贡翘,token可以偽造蹈矮,這是其一,其二鸣驱,token前端存在泛鸟,但后端可能已經(jīng)失效。所以采用后端的一層校驗(yàn)丐巫,確保權(quán)限token的準(zhǔn)確性谈况。就要使用到axios中的攔截器(interceptors)。
實(shí)現(xiàn)思路:如果前端有token 递胧,每次發(fā)送請求的時候碑韵,把token 發(fā)送給后端,后端按到token后缎脾,進(jìn)行校驗(yàn)祝闻,之后把校驗(yàn)結(jié)果在接口中反饋
請求攔截:
axios.interceptors.request.use(requestConfig => {
if(store.state.token){
config.headers.Authorization = ${store.state.token}
}
return requestConfig
},err => {
return Promise.reject(err)
})
響應(yīng)攔截:后端拿到Token,發(fā)現(xiàn)token ,返回401(前后端約定好的),此時前端就知道作何處理
// response interceptor
axios.interceptors.response.use(
response => {
// 如果返回的狀態(tài)碼為200遗菠,說明接口請求成功联喘,可以正常拿到數(shù)據(jù)
// 否則的話拋出錯誤
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
// 服務(wù)器狀態(tài)碼不是2開頭的的情況
// 這里可以跟你們的后臺開發(fā)人員協(xié)商好統(tǒng)一的錯誤狀態(tài)碼
// 然后根據(jù)返回的狀態(tài)碼進(jìn)行一些操作,例如登錄過期提示辙纬,錯誤提示等等
// 下面列舉幾個常見的操作豁遭,其他需求可自行擴(kuò)展
error => {
if (error.response.status) {
switch (error.response.status) {
// 401: 未登錄
// 未登錄則跳轉(zhuǎn)登錄頁面,并攜帶當(dāng)前頁面的路徑
// 在登錄成功后返回當(dāng)前頁面贺拣,這一步需要在登錄頁操作蓖谢。
case 401:
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
break;
// 403 token過期
// 登錄過期對用戶進(jìn)行提示
// 清除本地token和清空vuex中token對象
// 跳轉(zhuǎn)登錄頁面
case 403:
Message({
message: '登錄過期,請重新登錄',
duration: 1000,
forbidClick: true
});
// 清除token
localStorage.removeItem('token');
store.commit('loginSuccess', null);
// 跳轉(zhuǎn)登錄頁面譬涡,并將要瀏覽的頁面fullPath傳過去闪幽,登錄成功后跳轉(zhuǎn)需要訪問的頁面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
// 404請求不存在
case 404:
Message({
message: '網(wǎng)絡(luò)請求不存在',
duration: 1500,
forbidClick: true
});
break;
// 其他錯誤,直接拋出錯誤提示
default:
Message({
message: error.response.data.message,
duration: 1500,
forbidClick: true
});
}
return Promise.reject(error.response);
}
}
});
對于token
token涡匀,一般是在登錄完成之后盯腌,將用戶的token通過localStorage或者cookie存在本地,然后用戶每次在進(jìn)入頁面的時候陨瘩,會首先從本地存儲中讀取token腕够,如果token存在說明用戶已經(jīng)登陸過级乍,則更新vuex中的token狀態(tài)。然后燕少,在每次請求接口的時候卡者,都會在請求的header中攜帶token,服務(wù)器就可以根據(jù)你攜帶的token來判斷你的登錄是否過期客们,如果沒有攜帶崇决,則說明沒有登錄過。