登录突然失效: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 提示,就能在不改业务的前提下恢复稳定登录。

相关推荐
济6171 分钟前
嵌入式C语言(第一期)
c语言·开发语言
XiaoHu02072 分钟前
Linux多线程(详细全解)
linux·运维·服务器·开发语言·c++·git
苏宸啊15 分钟前
C++(二)类和对象上篇
开发语言·c++
双向3320 分钟前
RAG的下一站:检索增强生成如何重塑企业知识中枢?
前端
拖拉斯旋风22 分钟前
从零开始:使用 Ollama 在本地部署开源大模型并集成到 React 应用
前端·javascript·ollama
superman超哥29 分钟前
双端迭代器(DoubleEndedIterator):Rust双向遍历的优雅实现
开发语言·后端·rust·双端迭代器·rust双向遍历
asing30 分钟前
🤯 为什么我的收银台在鸿蒙系统“第一次返回”死活拦不住?一次差点背锅的排查实录
前端·harmonyos
德育处主任31 分钟前
『NAS』在群晖部署图片压缩工具-Squoosh
前端·javascript·docker
Hao_Harrision33 分钟前
50天50个小项目 (React19 + Tailwindcss V4) ✨| ThreeDBackgroundBoxes(3D背景盒子组件)
前端·3d·typescript·react·tailwindcss·vite7
加个鸡腿儿36 分钟前
经验分享2:SSR 项目中响应式组件的闪动陷阱与修复实践
前端·css·架构