页面发送http请求,很多情况我们要对请求和其响应进行特定的处理;如果请求数非常多,单独对每一个请求进行处理会变得非常麻烦,程序的优雅性也会大打折扣。好在强大的axios为开发者提供了这样一个API:拦截器。拦截器分为 请求(request)拦截器和 响应(response)拦截器。
axios拦截器简单介绍
请求拦截器
1 axios.interceptors.request.use(function (config) { 2 // 在发起请求请做一些业务处理 3 return config; 4 }, function (error) { 5 // 对请求失败做处理 6 return Promise.reject(error); 7 });
响应拦截器
1 axios.interceptors.response.use(function (response) { 2 // 对响应数据做处理 3 return response; 4 }, function (error) { 5 // 对响应错误做处理 6 return Promise.reject(error); 7 });
vue添加axios拦截器
安装 axios
npm install axios –save-dev
新建文件 axios.js
开始统一封装axios, 首先引入axios、qs依赖
1 import axios from "axios"; 2 import qs from "qs";
然后创建一个axios实例,这个process.env.BASE_URL在config/dev.evn.js、prod.evn.js里面进行配置:
1 /****** 创建axios实例 ******/ 2 const service = axios.create({ 3 baseURL: process.env.BASE_URL, // api的base_url 4 timeout: 5000 // 请求超时时间 5 });
使用request拦截器对axios请求配置做统一处理
1 service.interceptors.request.use(config => { 2 app.$vux.loading.show({ 3 text: '数据加载中……' 4 }); 5 config.method === 'post' 6 ? config.data = qs.stringify({...config.data}) 7 : config.params = {...config.params}; 8 config.headers['Content-Type'] = 'application/x-www-form-urlencoded'; 9 return config; 10 }, error => { //请求错误处理 11 app.$vux.toast.show({ 12 type: 'warn', 13 text: error 14 }); 15 Promise.reject(error) 16 } 17 );
对response做统一处理
1 service.interceptors.response.use( 2 response => { //成功请求到数据 3 app.$vux.loading.hide(); 4 //这里根据后端提供的数据进行对应的处理 5 if (response.data.result === 'TRUE') { 6 return response.data; 7 } else { 8 app.$vux.toast.show({ 9 //常规错误处理 10 type: 'warn', 11 text: response.data.data.msg 12 }); 13 } 14 }, 15 error => { //响应错误处理console.log('error'); 16 console.log(error); 17 console.log(JSON.stringify(error)); 18 let text = JSON.parse(JSON.stringify(error)).response.status === 404 19 ? '404' 20 : '网络异常,请重试'; 21 app.$vux.toast.show({ 22 type: 'warn', 23 text: text 24 }); 25 return Promise.reject(error) 26 } 27 )
将axios实例暴露出去
1 export default service;
这样一个简单的拦截器就完成了
在main.js中进行引用,并配置一个别名($ajax)来进行调用
1 import axios from 'axios' 2 import '../axios.js' //axios.js的路径 3 4 Vue.prototype.$ajax = axios
应用:一个简单的登录接口
1 this.$ajax({ 2 method: 'post', 3 url: '/login', 4 data: { 5 'userName': 'haha', 6 'password': '123456' 7 } 8 }).then(res => { 9 console.log(res) 10 })
使用场景
eg: axios拦截器对路由进行拦截
1.路由拦截
在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录。如果用户已经登录,则顺利进入路由,否则就进入登录页面。
1 const routes = [ 2 { 3 path: '/', 4 name: '/', 5 component: Index 6 }, 7 { 8 path: '/repository', 9 name: 'repository', 10 meta: { 11 requireAuth: true, // 添加该字段,表示进入这个路由是需要登录的 12 }, 13 component: Repository 14 }, 15 { 16 path: '/login', 17 name: 'login', 18 component: Login 19 } 20 ];
定义完路由后,我们主要是利用vue-router提供的钩子函数beforeEach()对路由进行判断。
1 router.beforeEach((to, from, next) => { 2 if (to.meta.requireAuth) { // 判断该路由是否需要登录权限 3 if (token) { // 判断当前的token是否存在 4 next(); 5 } 6 else { 7 next({ 8 path: '/login', 9 query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由 10 }) 11 } 12 } 13 else { 14 next(); 15 } 16 })
to.meta中是我们自定义的数据,其中就包括我们刚刚定义的requireAuth字段
通过这个字段来判断该路由是否需要登录权限
需要的话,同时当前应用不存在token,则跳转到登录页面,进行登录。登录成功后跳转到目标路由。
这种方式只是简单的前端路由控制,并不能阻止用户访问,假设有一种情况:当前token失效了,但是token依然保存在本地。这时候你去访问需要登录权限的路由时,实际上应该让用户重新登录。这时候就需要结合 http 拦截器 + 后端接口返回的http 状态码来判断。
2.拦截器
要想统一处理所有http请求和响应,就得用上 axios 的拦截器。通过配置http response inteceptor,当后端接口返回401 Unauthorized(未授权),让用户重新登录。
1 // http request 拦截器 2 axios.interceptors.request.use( 3 config => { 4 if (stoken) { // 判断是否存在token,如果存在的话,则每个http header都加上token 5 config.headers.Authorization = `token ${store.state.token}`; 6 } 7 return config; 8 }, 9 err => { 10 return Promise.reject(err); 11 }); 12 13 // http response 拦截器 14 axios.interceptors.response.use( 15 response => { 16 return response; 17 }, 18 error => { 19 if (error.response) { 20 switch (error.response.status) { 21 case 401: 22 // 返回 401 清除token信息并跳转到登录页面 23 24 router.replace({ 25 path: 'login', 26 query: {redirect: router.currentRoute.fullPath} 27 }) 28 } 29 } 30 return Promise.reject(error.response.data) // 返回接口返回的错误信息 31 });
链接:https://hupeip.github.io/2018/10/08/axios%E6%8B%A6%E6%88%AA%E5%99%A8/
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。