前言
本文讲解程序小bug,Axios拿不到token的排查全流程,如果有大佬有更好的解决办法,求求大佬教教我!!
具备条件
- token已有,且存在localStorage
- 拦截器也已经将token带上
但是首页请求响应却是未登录???
排错流程
登录流程如下:
graph TD
点击登录 --> 后端返回token --> 前端将token存入localStorage
在这些流程都成立的情况下,后续接口居然还是未登录
检查接口发现响应确实是未登录
更神奇的是点击刷新以后又能够访问成功了?
不知道有没有大佬猜出是什么原因了
这里我们暂时先不考虑为什么刷新就又可以登录,后续我们就能够理解这是为什么了
-
根据后端逻辑判断,有以下可能
- redis的信息数据过期
- token没传,后端拦截器未放行
很显然就是token没传,后端拦截器未放行,因为我们一登录就寄了
检查请求头发现确实如此,在请求头报文中果然没有token数据
- 接下来分析为什么没有token?
既然没有拿到很有可能是localStorage里面没有数据
查看localStorage里发现在点击登录的瞬间,确确实实是将数据存入localStorage里面了
接下来可以判断是在Axios里面出现问题了,以下是Axios的主要代码
这里我们是通过以下的代码去拿到token
let data = localStorage.getItem("userInfo") || "";
let token: string = "";
if (data) {
token = JSON.parse(data).token;
}
然后将token放入请求头中发送请求,相信大佬在看到这段代码估计就看出问题所在了
无奈我只是一个小菜鸡,通过打印token发现,确实是没拿到token
这里我就在思考一个问题,明明已经通过let data = localStorage.getItem("userInfo") || "";去拿了,localStorage里面也已经有数据了,为什么会拿不到?很奇怪
接下来我就发现了一个事情,这段打印的代码执行是在我进入到登录页面时执行的,也就是说在我进入到登录页时,axios就被挂载到了app中,这时候 同步代码就会被执行,但是这个时候我的localStorage里面是没有数据的,所以才拿不到!!!!!
接下来我就去拦截器内部做打印token操作
可以看到,不管是外面的还是里面的都是空,所以请求才没带token
这里我们就能够发现一个非常重要的事情
“拦截器内部token”居然打印了两次,这可能不奇怪,因为登录的时候发送了一次请求,主页拿数据一次请求,但是“token”只打印了一次,这就很奇怪了
至此,bug就找出来了,这也就是导致我们拿不到token的原因
在axios加载的时候,同步代码会被执行,拦截器只有在发送axios请求时才会被触发
这也就解释了为什么刷新之后居然就能够发送请求成功了
刷新会让axios再次被重新加载,此时在localStorage里面早就已经有登录的数据,直接就可以拿到了
处理方案
接下来就是处理方案了
我们可以使用pinia做数据存储,登录成功以后就将数据放入pinia
这里我使用的方案是,既然去拿的token是空的,而且每次发送请求都会触发拦截器,那直接在拦截器里面在其使用token之前,刷新token不就行了,这也算是一种偷懒的方法了,不过能解决bug的代码就是好代码!!!
只需要修改拦截器
至此bug就解决了
总结
本文讲解了解决Axios拿不到token的小bug的排查全流程,如果有大佬有更好的解决办法,求求大佬教教我!!
核心就是一句话:axios加载的时候,同步代码会被执行,拦截器只有在发送axios请求时才会被触发