axios介绍
什么是axios
axios是一个基于Promise的HTTP库,可以用在浏览器或node.js中。
axios特点:
- 从浏览器中创建XMLHTTPRequest
- 从node.js端创建http请求
- 支持PromiseAPI
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF
axios拦截器
为什么使用拦截器
页面发送http请求,很多情况我们要对请求和其响应进行特定的处理;例如每个请求都附带后端返回的token,拿到response之前loading动画的展示等。如果请求数非常多,这样处理起来会非常的麻烦,程序的优雅性也会大打折扣。在这种情况下,axios为开发者提供了这样一个API:拦截器。拦截器分为 请求(request)拦截器和 响应(response)拦截器。
- 在请求和响应被then或catch处理前拦截它们。
//添加请求拦截器
axios.interceptors.request.use(function(config){
//在请求发送之前做些什么
return config
},function(error){
//对请求错误做些什么
return Promise.reject(error)
})
//添加响应请求
axios.interceptors.reponse.use(function(reponse){
//对响应数据做些什么
return reponse
},function(error){
//对响应错误做些什么
return Promise.reject(error)
})
- 添加拦截器使用
use
- 移除拦截器使用
eject
var myInterceptors = axios.interceptors.request.use()
//移除拦截器
axios.interceptors.request.eject(myInterceptors)
- axios自定义实例添加拦截器
//自定义实例
var instance = axios.create()
//添加拦截器
instance.interceptors.request.use()
axios取消请求
- 使用
cancel token
取消请求 - 可以使用 CancelToken.source 工厂方法创建 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 参数是可选的)
source.cancel('Operation canceled by the user.');
- 还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
});
// 取消请求
cancel();
借助axios的拦截器实现Vue.js中登陆状态校验
后台系统中,不是每个页面都需要登录权限,所以要对需要进行登录权限的页面做好标记,使用路由的meta标签
{
path: '/userInfo',
name: '/userInfo',
meta: {
requireAuth: true // 该路由需要登录权限校验
},
component: userInfo
},{
path: '/userInfo',
name: '/userInfo',
// 该路由需要登录权限校验
component: userInfo
}
定义一起全局前置守卫,每次跳转路由,进行权限校验
router.beforeEach((to,from,next) => {
if(to.meta.requireAuth){ //如果路由需要校验权限
/*
从vuex拿出token码,说明已经登录
(前端的Token可以伪造,并不靠谱)
*/
if(store.state.token){
next() //正常跳转页面
}else{
next({
path: "/login",
query: {redirect: to.fullPath}
/*将跳转的路由地址作为参数带给登录页,登录成功后跳转回改页面 */
})
}
}else {
//如果不要校验,直接进入登录页
next()
}
})
但以上的实现存在问题,token可以伪造,这是其一,其二,token前端存在,但后端可能已经失效。所以采用后端的一层校验,确保权限token的准确性。就要使用到axios中的拦截器(interceptors)。
实现思路:如果前端有token ,每次发送请求的时候,把token 发送给后端,后端按到token后,进行校验,之后把校验结果在接口中反馈
请求拦截:
axios.interceptors.request.use(requestConfig => {
if(store.state.token){
config.headers.Authorization = ${store.state.token}
}
return requestConfig
},err => {
return Promise.reject(err)
})
响应拦截:后端拿到Token,发现token ,返回401(前后端约定好的),此时前端就知道作何处理
// response interceptor
axios.interceptors.response.use(
response => {
// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
// 否则的话抛出错误
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
// 服务器状态码不是2开头的的情况
// 这里可以跟你们的后台开发人员协商好统一的错误状态码
// 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
// 下面列举几个常见的操作,其他需求可自行扩展
error => {
if (error.response.status) {
switch (error.response.status) {
// 401: 未登录
// 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401:
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
break;
// 403 token过期
// 登录过期对用户进行提示
// 清除本地token和清空vuex中token对象
// 跳转登录页面
case 403:
Message({
message: '登录过期,请重新登录',
duration: 1000,
forbidClick: true
});
// 清除token
localStorage.removeItem('token');
store.commit('loginSuccess', null);
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
// 404请求不存在
case 404:
Message({
message: '网络请求不存在',
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存在本地,然后用户每次在进入页面的时候,会首先从本地存储中读取token,如果token存在说明用户已经登陆过,则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,服务器就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。