You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue+Laravel多文件API调用:Axios异常返回处理与代码结构优化

问题解决与代码优化方案

一、解决Axios非2XX状态码错误无法传递到组件的问题

Axios默认会把非2XX状态码的响应抛出异常,你需要在Axios实例中添加响应拦截器,统一处理错误,把后端返回的错误信息正常传递给调用方。

1. 配置Axios拦截器(核心API配置文件)

import axios from 'axios'

// 创建Axios实例
const apiClient = axios.create({
  baseURL: '/api', // Laravel后端API前缀
  headers: {
    'Content-Type': 'application/json',
  },
})

// 响应拦截器:处理错误响应
apiClient.interceptors.response.use(
  response => response, // 正常响应直接返回
  error => {
    // 提取后端返回的错误信息,适配Laravel的返回格式
    const errorMessage = error.response?.data?.message || '请求失败,请稍后重试'
    // 包装错误后抛出,让组件能捕获到具体信息
    return Promise.reject(new Error(errorMessage))
  }
)

export default apiClient

2. 模型API文件(如models/User.js)

import apiClient from '../api.js'

export default {
  login(credentials) {
    return apiClient.post('/login', credentials)
  },
  // 其他用户相关API...
}

3. 在Login.vue组件中处理错误

<template>
  <div>
    <input v-model="form.email" type="email" placeholder="邮箱">
    <input v-model="form.password" type="password" placeholder="密码">
    <button @click="handleLogin">登录</button>
    <p v-if="errorMsg" class="text-red-500">{{ errorMsg }}</p>
  </div>
</template>

<script>
import UserApi from '@/models/User.js'

export default {
  data() {
    return {
      form: {
        email: '',
        password: ''
      },
      errorMsg: ''
    }
  },
  methods: {
    async handleLogin() {
      this.errorMsg = ''
      try {
        const response = await UserApi.login(this.form)
        // 登录成功逻辑:存token、跳转首页等
        console.log('登录成功', response.data)
      } catch (err) {
        // 捕获拦截器传递的错误信息并展示
        this.errorMsg = err.message
      }
    }
  }
}
</script>

二、更合理的代码组织方案

推荐按API核心配置、拦截器、模型API拆分目录,结构清晰、职责单一,便于后续维护扩展:

目录结构

src/
├── api/
│   ├── index.js          # Axios实例创建、拦截器挂载
│   ├── interceptors/
│   │   ├── request.js    # 请求拦截器(如添加token)
│   │   └── response.js   # 响应拦截器(统一错误处理)
│   └── models/
│       ├── User.js       # 用户模块API
│       ├── Post.js       # 文章模块API
│       └── ...           # 其他模型API
└── components/
    └── Login.vue         # 登录组件

各文件职责说明

  1. api/index.js:创建Axios实例并挂载拦截器
import axios from 'axios'
import requestInterceptor from './interceptors/request'
import responseInterceptor from './interceptors/response'

const apiClient = axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL || '/api',
  headers: {
    'Content-Type': 'application/json',
  },
})

// 挂载请求/响应拦截器
apiClient.interceptors.request.use(requestInterceptor)
apiClient.interceptors.response.use(
  response => response,
  responseInterceptor
)

export default apiClient
  1. api/interceptors/request.js:处理请求前置逻辑
export default function requestInterceptor(config) {
  // 从localStorage获取token,添加到请求头
  const token = localStorage.getItem('auth_token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
}
  1. api/interceptors/response.js:精细化处理不同错误场景
export default function responseInterceptor(error) {
  // 网络异常处理
  if (!error.response) {
    return Promise.reject(new Error('网络异常,请检查网络连接'))
  }

  const { status, data } = error.response
  let errorMsg = '请求失败,请稍后重试'

  // 适配Laravel常见状态码的错误提示
  switch (status) {
    case 401:
      errorMsg = data.message || '登录已过期,请重新登录'
      // 可在此添加跳转登录页的逻辑
      break
    case 422:
      // 提取表单验证的第一个错误信息
      errorMsg = Object.values(data.errors)[0][0]
      break
    case 403:
      errorMsg = data.message || '权限不足,无法访问'
      break
    default:
      errorMsg = data.message || errorMsg
  }

  return Promise.reject(new Error(errorMsg))
}
  1. api/models/User.js:只封装用户相关API
import apiClient from '../index.js'

export const UserApi = {
  login(credentials) {
    return apiClient.post('/login', credentials)
  },
  logout() {
    return apiClient.post('/logout')
  },
  getUserInfo() {
    return apiClient.get('/user')
  }
}

export default UserApi

这种拆分方式让每个模块职责明确,拦截器逻辑与API调用分离,后续新增模型或修改拦截规则时不会互相干扰,更符合模块化开发的思路。

内容的提问来源于stack exchange,提问作者iamsubingyawali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 00:15:43