Debug:Axios你是真的坑!把我的token藏哪了!

4,895 阅读3分钟

前言

本文讲解程序小bug,Axios拿不到token的排查全流程,如果有大佬有更好的解决办法,求求大佬教教我!!

具备条件

  • token已有,且存在localStorage
  • 拦截器也已经将token带上

但是首页请求响应却是未登录???

image.png

排错流程

登录流程如下:

graph TD
点击登录 --> 后端返回token --> 前端将token存入localStorage

在这些流程都成立的情况下,后续接口居然还是未登录

动画3.gif

检查接口发现响应确实是未登录

image.png

更神奇的是点击刷新以后又能够访问成功了?

动画3.gif

不知道有没有大佬猜出是什么原因了

这里我们暂时先不考虑为什么刷新就又可以登录,后续我们就能够理解这是为什么了

  • 根据后端逻辑判断,有以下可能

    • redis的信息数据过期
    • token没传,后端拦截器未放行

很显然就是token没传,后端拦截器未放行,因为我们一登录就寄了

检查请求头发现确实如此,在请求头报文中果然没有token数据

image.png

  • 接下来分析为什么没有token?

既然没有拿到很有可能是localStorage里面没有数据

查看localStorage里发现在点击登录的瞬间,确确实实是将数据存入localStorage里面了

image.png

接下来可以判断是在Axios里面出现问题了,以下是Axios的主要代码

image.png 这里我们是通过以下的代码去拿到token

let data = localStorage.getItem("userInfo") || "";
let token: string = "";
if (data) {
  token = JSON.parse(data).token;
}

然后将token放入请求头中发送请求,相信大佬在看到这段代码估计就看出问题所在了

无奈我只是一个小菜鸡,通过打印token发现,确实是没拿到token

image.png

这里我就在思考一个问题,明明已经通过let data = localStorage.getItem("userInfo") || "";去拿了,localStorage里面也已经有数据了,为什么会拿不到?很奇怪

接下来我就发现了一个事情,这段打印的代码执行是在我进入到登录页面时执行的,也就是说在我进入到登录页时,axios就被挂载到了app中,这时候 同步代码就会被执行,但是这个时候我的localStorage里面是没有数据的,所以才拿不到!!!!!

接下来我就去拦截器内部做打印token操作

image.png

可以看到,不管是外面的还是里面的都是空,所以请求才没带token

这里我们就能够发现一个非常重要的事情

“拦截器内部token”居然打印了两次,这可能不奇怪,因为登录的时候发送了一次请求,主页拿数据一次请求,但是“token”只打印了一次,这就很奇怪了

至此,bug就找出来了,这也就是导致我们拿不到token的原因

在axios加载的时候,同步代码会被执行,拦截器只有在发送axios请求时才会被触发

这也就解释了为什么刷新之后居然就能够发送请求成功了

刷新会让axios再次被重新加载,此时在localStorage里面早就已经有登录的数据,直接就可以拿到了

处理方案

接下来就是处理方案了

我们可以使用pinia做数据存储,登录成功以后就将数据放入pinia

这里我使用的方案是,既然去拿的token是空的,而且每次发送请求都会触发拦截器,那直接在拦截器里面在其使用token之前,刷新token不就行了,这也算是一种偷懒的方法了,不过能解决bug的代码就是好代码!!!

只需要修改拦截器

image.png

至此bug就解决了

总结

本文讲解了解决Axios拿不到token的小bug的排查全流程,如果有大佬有更好的解决办法,求求大佬教教我!!

核心就是一句话:axios加载的时候,同步代码会被执行,拦截器只有在发送axios请求时才会被触发