登录突然失效:Axios 拦截器判空、localStorage 脏数据与环境变量踩坑

登录突然失效:Axios 拦截器判空、localStorage 脏数据与环境变量踩坑

现象:最开始能登录,后来加了"普通用户登录/角色选择"之后,点击登录按钮没反应;控制台报错:

  • TypeError: Cannot read properties of undefined (reading 'status')(request.js)
  • TypeError: Cannot read properties of null (reading 'token')(request.js)

结论:登录业务本身没坏,坏的是异常分支的健壮性 :网络失败时 Axios 没有 response、localStorage 存了脏值导致 token 读取崩溃,最终让页面看起来"按钮失灵"。


1. 背景与系统结构

  • 前端:Vue3 + Vite + Element Plus + Axios
  • 后端:SpringBoot(端口 9090

前端通过 baseURL = import.meta.env.VITE_BASE_URL 请求后端接口(例如 /login)。


2. 现象与报错意味着什么

2.1 报错 1:

Cannot read properties of undefined (reading 'status')

典型代码形态(伪代码):

js 复制代码
// 响应拦截器 error 分支
if (error.response.status === 404) {
  ...
}

为什么会出现 error.response === undefined

Axios 的错误分两大类:

  1. HTTP 错误(有响应) :比如 404、500,此时 error.response 存在。
  2. 网络层错误(无响应)
  • 后端没启动/端口不对
  • 后端重启中/短暂不可用
  • 请求超时
  • 跨域被浏览器拦截
  • 连接被拒绝(ERR_CONNECTION_REFUSED)

这类情况下,浏览器根本拿不到 HTTP 响应,所以 Axios 也就没有 error.response

因此直接读 error.response.status 就会抛异常,把你的 Promise 链直接打断

页面表现:点击登录无反应(其实是 JS 报错中断了后续逻辑)。

2.2 报错 2:

Cannot read properties of null (reading 'token')

典型代码:

js 复制代码
let user = JSON.parse(localStorage.getItem('xm-user') || '{}')
config.headers['token'] = user.token || ''

为什么 JSON.parse 之后会是 null?

当 localStorage 中保存的是字符串:

text 复制代码
"null"

那么:

js 复制代码
JSON.parse('null') // => null

于是 user 变成 null,再读 user.token 就报错。

这种"突然坏掉"最常见的原因是:某次流程(例如退出/切换角色)把 xm-user 写成了 null 或非法 JSON,之后每次请求都会在拦截器崩掉。


3. 为什么"没改关键代码,但突然不能登录"?

关键点:成功路径一直没问题,问题出在"异常路径"。

以前能登录,是因为:

  • 后端一直稳定可用 → 没触发网络错误分支
  • localStorage 没出现脏值 → 没触发 token 读取崩溃

后来突然不行,往往只需要发生一次:

  • 后端短暂不可用(哪怕 1 次)
  • 或者某次逻辑把 xm-user 写成了 "null"

就会触发拦截器报错,从用户视角看就是"按钮突然不灵"。

加了"普通用户登录/角色选择"后,更容易触发边界情况:

  • 初次进入未登录、token 为空
  • 切换角色导致缓存被覆盖
  • 退出逻辑写错,把对象置空

这些都不是"登录关键业务逻辑",但会让系统更频繁进入异常分支,从而暴露隐患。


4. 排查思路(推荐按这个顺序)

4.1 先看 Network:请求到底有没有成功发出去?

  • 如果请求状态是 200/401/500 → 属于 HTTP 有响应
  • 如果请求是 (failed)ERR_CONNECTION_REFUSEDCORS → 属于 网络层无响应

网络层无响应时,error.response 一定可能是 undefined

4.2 再看 localStorage:xm-user 是不是脏了?

打开 DevTools → Application → Local Storage:

  • xm-user 如果是 "null" 或非法 JSON → 一定会触发 token 报错。

快速修复:删掉 xm-user 再刷新页面。

4.3 最后核对环境变量:是否跑到 production 配置?

  • npm run dev 使用 .env.development
  • npm run build / preview 使用 .env.production

如果 .env.production 写错(例如 http://:9090 缺 host),构建产物一定连不上后端。


5. 最小改动修复(不改变原业务)

本次修复目标:只增强容错,不改原有登录成功/失败逻辑与接口协议

5.1 request.js:对 error.response 判空

核心思想:网络错误时没有 response,不要读 status

js 复制代码
if (!error || !error.response) {
  ElMessage.error('网络异常:无法连接服务器')
  return Promise.reject(error)
}

这样就不会再出现 reading 'status' 的 JS 崩溃。

5.2 request.js:对 localStorage 的 xm-user 做健壮解析

核心思想:localStorage 可能是 "null"、空字符串、非法 JSON、或解析后不是对象。

js 复制代码
const userStr = localStorage.getItem('xm-user')
let user = {}
try {
  user = userStr ? JSON.parse(userStr) : {}
} catch (e) {
  user = {}
}
if (!user || typeof user !== 'object') user = {}
config.headers['token'] = user.token || ''

这样即使缓存坏了,也不会因为读 token 崩溃。

5.3 Login.vue:为登录请求补 .catch 提示

核心思想:失败时要给用户反馈,否则看起来像"按钮没反应"。

js 复制代码
request.post('/login', data.form)
  .then(...)
  .catch(err => {
    ElMessage.error(err?.message || '登录失败')
  })

5.4 修正 .env.production 的 baseURL

如果你以后跑构建产物(build/preview/部署),要确保:

dotenv 复制代码
VITE_BASE_URL='http://localhost:9090'

避免出现 http://:9090 这种无效地址。


6. 结果

  • npm run dev 下登录恢复正常
  • 网络异常/后端不可达时不再崩溃,而是明确提示"无法连接服务器"
  • localStorage 脏数据不再导致拦截器读 token 崩溃

7. 预防建议(同类项目通用)

  • Axios 拦截器里永远不要假设 error.response 存在
  • localStorage 读取要做容错:解析失败、null、类型不对都要兜底
  • 登录请求必须有 .catch(哪怕只提示一句)
  • 开发/生产环境变量要区分清楚,避免 build 产物用错 baseURL

附:一句话总结

这次"突然不能登录"不是后端登录接口坏了,而是前端在网络错误/缓存异常时直接抛 JS 异常导致逻辑中断;通过对 error.responsexm-user 做判空容错,并补充 .catch 提示,就能在不改业务的前提下恢复稳定登录。

相关推荐
IT_陈寒3 小时前
Vue3性能优化实战:这7个技巧让我的应用加载速度提升40%
前端·人工智能·后端
早川不爱吃香菜3 小时前
MCP 教程:将 Figma 设计稿转化为前端代码
前端·figma
月明长歌3 小时前
【码道初阶】【Leetcode105&106】用遍历序列还原二叉树:前序+中序、后序+中序的统一套路与“先建哪边”的坑
java·开发语言·数据结构·算法·leetcode·二叉树
修炼前端秘籍的小帅3 小时前
PinMe——极简、免费和无需服务器的开源前端部署工具
前端
XXYBMOOO3 小时前
基于 HTML5 Canvas 的终端日志流可视化实现(支持多 Pane / 运维模式)
运维·前端·html5
悟能不能悟4 小时前
vue导出excel文件
前端·vue.js·excel
Oliver_LaVine4 小时前
java后端实现全链路日志ID记录
java·开发语言·spring
闭上眼让寒冷退却4 小时前
知识库发布按钮引发的查询版本发布状态(轮询?——>调用后端接口)以及api接口设计学习
java·前端·javascript
木头软件4 小时前
批量将 Word 文档重命名为其标题
开发语言·c#·word