1. 前言
本篇将为 axios 请求库添加请求拦截器、响应拦截器,通过它们,就可以在请求之前,或者请求结束以后定制一些个性化需求。
2. 拦截器
关于拦截器的详细文档,可访问官方地址:https://www.axios-http.cn/docs/interceptors ,官方对它的解释是:
在请求或响应被 then 或 catch 处理前拦截它们。
axios.interceptors.request.use(function (config) { return config; }, function (error) { return Promise.reject(error); });
axios.interceptors.response.use(function (response) { return response; }, function (error) { return Promise.reject(error); });
|
3. 整合到项目中
编辑 axios.js 文件,添加上述代码,注意,需要将实例名改成之前定义好的 instance, 代码如下:
import axios from "axios";
const instance = axios.create({ baseURL: "/api", timeout: 7000, })
instance.interceptors.request.use(function (config) { return config; }, function (error) { return Promise.reject(error) });
instance.interceptors.response.use(function (response) { return response.data }, function (error) { return Promise.reject(error) })
export default instance;
|
4. 定制请求拦截器
在用户登录成功后,我们已经将 Token 令牌存储到了 Cookie 中,但是,光存储还不够,当我们请求受保护的接口时,需要将它动态添加到请求头中才行。这个工作,就可以在请求拦截器中来完成。
4.1 给请求头添加 Token 令牌
编辑 axios.js 中请求拦截器的逻辑,代码如下:
import { getToken } from "@/composables/auth";
instance.interceptors.request.use(function (config) { const token = getToken() console.log('统一添加请求头中的 Token:' + token)
if (token) { config.headers['Authorization'] = 'Bearer ' + token }
return config; }, function (error) { return Promise.reject(error) });
|
上述代码中,我们在请求拦截器中先是获取了 Cookie 中存储的 Token 令牌,在不为空的情况下,将其添加到请求头中,按后端的规范,key 为 Authorization, 值为 Bearer + 中间空一格 + 令牌 的格式。
5. 定制响应拦截器
当通过 axios 给后台服务发送请求时,若服务挂了,或者返回的状态码不在 2xx 范围内,比如 401 未授权等。我们可以统一在响应拦截器中来处理,给用户弹一个消息提示,这样交互上也更加友好。
修改响应拦截器的错误响应模块,代码如下:
import { showMessage} from '@/composables/util'
instance.interceptors.response.use(function (response) { }, function (error) {
let errorMsg = error.response.data.message || '请求失败' showMessage(errorMsg, 'error')
return Promise.reject(error) })
|
6. 全局路由拦截
6.1 全局前置守卫
const router = createRouter({ ... })
router.beforeEach((to, from, next) => { next() })
|
通过使用 router.beforeEach 注册一个全局前置守卫,每个守卫默认接受两个参数:
- to: 即将要进入的目标;
- from: 当前导航正要离开的路由;
- next : 可额外添加的参数,用于手动控制跳转哪个页面;
next() 必须设置,否则不会跳转目标路由。
6.2 后置钩子
有前置,就有后置。你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身,使用格式如下:
router.afterEach((to, from) => { })
|
可以在src下新建permission.js,将前置后置守卫代码放入,然后再main.js中去引用
import router from '@/router'
import '@/permission'
|
6.3 浏览器tab自动标题
这些信息是可以在后置路由中来获取到,然后用于动态设置页面标题,改造 permission.js , 代码如下:
router.afterEach((to, from) => { let title = (to.meta.title ? to.meta.title : '') + ' - Windblog' document.title = title })
|
6.4 路由跳转,添加登录判断
import router from '@/router/index' import { getToken } from '@/composables/auth' import { showMessage } from '@/composables/util'
router.beforeEach((to, from, next) => { console.log('==> 全局路由前置守卫')
let token = getToken() if (!token && to.path.startsWith('/admin')) { showMessage('请先登录', 'warning') next({ path: '/login' }) } else { next() } })
|
6. 结语
本篇我们主要给 axios 添加了请求拦截器和响应拦截器,在请求拦截器中,我们统一给每次请求的请求头添加了 Token 令牌;在响应拦截器中,先是优化了获取参数的格式,然后当请求失败时,统一弹出了消息提示,让交互更加友好。也添加了路由守卫,处理页面跳转时的一些必要性逻辑。