登录突然失效: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 的错误分两大类:
- HTTP 错误(有响应) :比如 404、500,此时
error.response存在。 - 网络层错误(无响应):
- 后端没启动/端口不对
- 后端重启中/短暂不可用
- 请求超时
- 跨域被浏览器拦截
- 连接被拒绝(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_REFUSED、CORS→ 属于 网络层无响应
网络层无响应时,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.developmentnpm 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.response 与 xm-user 做判空容错,并补充 .catch 提示,就能在不改业务的前提下恢复稳定登录。