Vue3中Vuex store dispatch方法的catch错误捕获不生效
Vue3 登录功能无法捕获后端错误提示问题修复
问题背景
开发Vue3应用登录功能时,凭证正确情况下登录、注册流程均可正常运行,但后端校验凭证不通过时,控制台无任何报错输出,无法获取服务端返回的拒绝响应,也无法向用户展示清晰的错误提示。
当前网络面板可看到后端返回响应内容:
{"error":"The provided credentials are incorrect","0":422}
现有问题代码
login.vue 组件逻辑
import store from "../store" import { useRouter } from "vue-router"; import { ref } from "vue"; const router = useRouter() const user = { email: '', password: '', remember : false } let errorMsg = ref(''); async function login(ev) { ev.preventDefault(); await store.dispatch('login', user) .then(()=> { router.push({ name: 'Dashboard' }) }) .catch((err) => { errorMsg = err.response.data.error console.log(err) }) }
Vuex Store 配置
import {createStore} from 'vuex' import axiosClient from "../axios"; const store = createStore({ state: { user: { data: {}, token: sessionStorage.getItem('TOKEN') } }, getters: {}, setters: {}, actions: { register({commit}, user) { return axiosClient.post('/register', user) .then(({data}) => { commit('setUser', data); return data; }) }, login({commit}, user) { return axiosClient.post('/login', user) .then(({data}) => { commit('setUser', data); return data; }) }, }, mutations: { logout: state => { state.user.data = {}; state.user.token = null; }, setUser: (state, userData)=> { state.user.token = userData.token; state.user.data = userData.user; sessionStorage.setItem('TOKEN', userData.token) } }, modules: {} }) export default store;
Axios 封装代码
import axios from "axios"; import store from "./store"; const axiosClient = axios.create({ baseURL: 'http://localhost:8000/api' }) axiosClient.interceptors.request.use(config=> { config.headers.Authorization = `Bearer ${store.state.user.token}` return config; }) export default axiosClient;
问题根因
- Axios未明确配置状态码校验规则,且缺少响应拦截器:如果后端返回错误时HTTP状态码为200,仅在响应体内携带422错误码,Axios会默认将请求判定为成功,不会进入catch分支;同时现有请求拦截器未补全错误回调,存在错误被吞的风险。
- 响应式变量赋值错误:
errorMsg为ref包装的响应式对象,直接给变量本身赋值会覆盖ref实例,导致响应式失效,既无法在控制台正确输出,也无法在页面渲染。 - 表单绑定对象写法错误:
user为普通常量对象,和表单v-model绑定时输入内容无法同步,存在发空参数的隐藏bug。 - async/await和Promise链式调用混用,逻辑可读性差,容易出现异常捕获遗漏。
修复方案
按以下步骤修改对应文件即可:
1. 补全Axios封装逻辑
import axios from "axios"; import store from "./store"; const axiosClient = axios.create({ baseURL: 'http://localhost:8000/api', // 明确判定2xx状态码为成功请求,其余状态码全部进入异常分支 validateStatus: (status) => status >= 200 && status < 300 }) // 补全请求拦截器错误回调 axiosClient.interceptors.request.use(config=> { config.headers.Authorization = `Bearer ${store.state.user.token}` return config; }, (error) => Promise.reject(error)) // 新增响应拦截器,兼容后端返回200状态码+响应体错误码的场景 axiosClient.interceptors.response.use((response) => { // 适配当前后端返回格式:响应体携带422错误码时手动抛出异常 if (response.data && response.data[0] === 422) { return Promise.reject({ response }) } return response; }, (error) => Promise.reject(error)) export default axiosClient;
2. 修复login.vue逻辑
import store from "../store" import { useRouter } from "vue-router"; import { ref } from "vue"; const router = useRouter() // 表单对象改为响应式ref,保证v-model输入同步 const user = ref({ email: '', password: '', remember : false }) const errorMsg = ref(''); async function login(ev) { ev.preventDefault(); // 提交前清空历史错误提示 errorMsg.value = '' try { // 统一使用async/await写法,避免捕获遗漏 await store.dispatch('login', user.value) router.push({ name: 'Dashboard' }) } catch (err) { // ref赋值必须通过.value属性,增加兜底提示 errorMsg.value = err.response?.data?.error || '登录失败,请检查网络后重试' console.log('登录请求异常:', err) } }
3. 模板增加错误提示渲染
在登录表单合适位置添加错误提示节点:
<div v-if="errorMsg" class="login-error" style="color: #f56c6c; margin: 8px 0;">{{ errorMsg }}</div>
内容的提问来源于stack exchange,提问作者Olalekan
相关产品推荐
相关产品推荐

