【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦

【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦

目录

【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦

一、为什么网络错误处理一定要下沉到 Axios 层

二、Axios 拦截器 interceptors

1、拦截器的基础应用

2、错误分级和策略映射的设计

3、错误对象标准化

三、结语


        作者:watermelo37

        ZEEKLOG优质创作者、华为云云享专家、阿里云专家博主、腾讯云“创作之星”特邀作者、火山KOL、支付宝合作作者,全平台博客昵称watermelo37。

        一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。



---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦

        有这样一句话:“在前端项目中,网络请求失败不是异常,而是常态。”真正拉开项目工程质量差距的,不是会不会用 axios,而是如何设计一套可维护、可扩展、可协作的网络错误处理体系。成熟的项目组有现成可用的axios网络封装设计,不成熟的项目组网络错误处理原始而杂乱,很多开发者在成熟的项目组开发了多年,依然不了解Axios 错误处理的设计封装,只处在知道有这个东西,而不知道如何设计的状态下。本文围绕 Axios 的拦截器机制,系统性分析可配置、可分级、可扩展的网络请求实战封装策略。

一、为什么网络错误处理一定要下沉到 Axios 层

        在项目中,如果常规错误处理放在业务层,就会需要给每个 async/await 都要写一段 try-catch,同一种错误(如 token 过期)被处理 N 次,UI 提示风格难以统一,后续想要改动极其痛苦:

// 典型的业务层污染 async function loadList() { try { const res = await getList() list.value = res.data } catch (e) { ElMessage.error('请求失败') } } 

        这肯定是不可取的,应该将错误分级并合并统一处理。对于网络错误的判断逻辑、分类、兜底策略,本就应该属于请求基础设施层。

二、Axios 拦截器 interceptors

        Axios 提供了两个关键拦截器,分别是请求拦截器和响应拦截器,可以用来行使不同的职责。

1、拦截器的基础应用

        网络请求一般有两大类失败,其一是HTTP / 网络层错误,比如断网、请求超时、上游错误(500/502/503)等。其二是业务层错误,比如 code !== 0(响应状态码是200,但业务状态异常)、token过期、权限问题等。

// src/utils/api.js import axios from 'axios'; import { ElMessage } from 'element-plus'; // 创建 axios 实例 const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '/api', timeout: 10000, }); // 请求拦截器(可选:添加 token 等) request.interceptors.request.use( (config) => { // 例如:从 localStorage 获取 token 并添加到请求头 const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); // 响应拦截是集中处理错误的核心 request.interceptors.response.use( (response) => { const { code, message, data } = response.data if (code !== 0) { return Promise.reject({ type: 'business', code, message }) } return data }, (error) => { const { response } = error; if (response) { // 有响应(HTTP 状态码 4xx / 5xx) switch (response.status) { case 400: ElMessage.error('请求参数错误'); break; case 401: ElMessage.error('未授权,请重新登录'); // 可跳转到登录页 // window.location.href = '/login'; break; case 403: ElMessage.error('拒绝访问'); break; case 404: ElMessage.error('请求资源不存在'); break; case 500: ElMessage.error('服务器内部错误'); break; default: ElMessage.error(`请求失败:${response.status}`); } } else if (error.request) { // 请求已发出但无响应(如网络错误、超时) ElMessage.error('网络异常,请检查网络连接'); } else { // 其他错误(如配置错误) ElMessage.error('请求配置错误'); } return Promise.reject(error); } ); export default request;

        此时业务层已经做到了数据与状态的解耦,状态问题和错误信息全部在拦截器阶段处理,返回给业务调用接口位置的只有数据:

// 在响应拦截器里面,返回的是response.data.data,所以业务层里面只会拿到数据 const data = await api.getUser() 

        这样业务层就不用关心 HTTP状态码和后端返回的具体结构,也不用对请求错误类型进行具体的区分了。

2、错误分级和策略映射的设计

        错误的严重程度是有等级的,不应该把所有的错误都按相同的方式处理,比如401,一般情况下应该去实现用户无感刷新,请求失败再提示用户重新登陆。

        只需要加上一个简单的策略映射设计:

const errorHandlers = { 401() { logout() router.push('/login') }, 403() { ElMessage.error('没有权限') }, default(err) { ElMessage.error(err.message || '请求失败') } } 

        并在拦截器中统一调度:

function handleBusinessError(err) { const handler = errorHandlers[err.code] || errorHandlers.default handler(err) } 

        这样就能根据状态码的不同,映射不同的处理方法,长期维护和拓展问题也解决了。

3、错误对象标准化

        很多项目后期痛苦的根源是 error 有时候是 string,有时候是 AxiosError,有时候是后端对象,所以需要永久地将错误处理的复杂度从业务层转移到基础设置层(即Axios)。以此来实现一个架构层面的收益。

        比如定义一个标准错误结构(这部分代码仅ts需要):

interface AppError { type: 'network' | 'business' code?: number message: string raw?: any } 

        然后在 Axios 层构造,举个例子:

axios.interceptors.response.use( res => { if (res.data.code !== 0) { return Promise.reject({ type: 'business', code: res.data.code, message: res.data.msg, raw: res }) } return res.data.data }, error => { return Promise.reject({ type: 'network', message: '网络异常,请稍后重试', raw: error }) } ) 

        那么在业务层就只需要面对一种 error 类型了,不用操心错误类型,业务代码降维:

try { await api.save() ElMessage.success('保存成功') } catch (err) { ElMessage.error(err.message) } 

三、结语

        一个成熟的 Axios 错误处理体系,应该能做到错误集中处理,业务代码干净,错误分级,有明确策略,错误结构统一,方便扩展,自然接入登录、权限、数据监控等模块。错误处理不是异常流程,而是系统设计的一部分。做好网络层的错误处理,实现数据与状态的解耦,会让业务层开发大有裨益。

         只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        其他热门文章,请关注:

        极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        Web Worker:让前端飞起来的隐形引擎

        测评:这B班上的值不值?在不同城市过上同等生活水平到底需要多少钱?

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

        DeepSeek:全栈开发者视角下的AI革命者

        TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

        通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

        高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图

        通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

      【前端实战】如何让用户回到上次阅读的位置?

        前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略

        深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题

        内存泄漏——海量数据背后隐藏的项目生产环境崩溃风险!如何避免内存泄漏

        MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver

        JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等

Read more

OpenClaw上身机器人,AI不仅能帮订外卖,还能替你跑腿了!

OpenClaw上身机器人,AI不仅能帮订外卖,还能替你跑腿了!

手把手教你一键部署OpenClaw(Clawdbot),2分钟搞定! 过去这些年,AI大多时候还只是待在屏幕里,帮人写写字、画画图或者跑个自动脚本。但最近 OpenClaw 生态彻底爆火,两个基于它的开源项目直接打破了虚拟与现实的界限。这消息一传出来,全球搞机器人和AI的极客们都坐不住了。 就在2月23号旧金山举行的 SF OpenClaw 黑客松上,ROSClaw 项目拿下了冠军。Irvin 团队搞出了一个中间连接层,把现在最火的开源 AI Agent 平台 OpenClaw 直接插到了真实的机器人硬件上。刚拿完奖,团队就大方地宣布把项目开源了。 手把手教你一键部署OpenClaw(Clawdbot),2分钟搞定! 手把手教你一键部署OpenClaw(Clawdbot),2分钟搞定! 具体是怎么做到的呢?他们通过智能插件把 OpenClaw 接到了机器人操作系统(ROS 2)上,还利用 WebRTC 技术实现了超低延迟的安全连接。这意味着你在地球任何一个角落,都能远程操控那些兼容 ROS 的机器人。AI

Java Web 厨艺交流平台系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

Java Web 厨艺交流平台系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着互联网技术的快速发展,线上交流平台逐渐成为人们分享知识和兴趣的重要渠道。厨艺作为一种普及性高且具有广泛受众的爱好,其线上交流需求日益增长。传统的厨艺交流方式受限于地域和时间,无法满足用户即时互动和内容共享的需求。因此,开发一个基于现代Web技术的厨艺交流平台具有重要的现实意义。该平台能够为用户提供菜谱分享、烹饪技巧讨论、社区互动等功能,有效促进厨艺爱好者的交流与合作。关键词:厨艺交流、互联网技术、Web平台、社区互动、菜谱分享。 本系统采用前后端分离架构,后端基于SpringBoot2框架实现高效稳定的服务端逻辑,前端使用Vue3构建动态响应式用户界面,数据库采用MySQL8.0存储结构化数据,并通过MyBatis-Plus简化数据访问层的开发。系统功能模块包括用户管理、菜谱发布、评论互动、收藏管理等,支持多角色权限控制,确保数据安全性和用户体验。系统还实现了图片上传、实时搜索、分页加载等扩展功能,提升了平台的实用性和易用性。关键词:SpringBoot2、Vue3、MyBatis-Plus、MySQL8.0、前后端分离。 数据表 用户信息数据表 用户注册及登录过程

Tauri 中嵌入百度网页:从 iframe 到 Webview 的迁移实践

Tauri 中嵌入百度网页:从 iframe 到 Webview 的迁移实践 问题描述 在开发 Tauri 桌面应用时,我们需要在一个插件窗口中嵌入百度首页。最初使用 iframe 实现,但遇到了点击无响应的问题。最终通过迁移到 Tauri 的 Webview API 成功解决。 问题背景 我们的应用使用 Tauri 2.0 + Vue 3 + TypeScript 技术栈。需求是在 src/plugins/baidu/index.vue 中实现一个显示百度首页的插件窗口,同时保留窗口控制按钮(最小化、最大化、关闭)。 初次尝试:使用 iframe 实现代码 <template> <

Cursor实战:Web版背单词应用开发演示

Cursor实战:Web版背单词应用开发演示

Cursor实战:Web版背单词应用开发演示 * 需求分析 * 自行编写需求文档 * 借助Cursor生成需求文档 * 前端UI设计 * 后端开发 * 项目结构 * 环境参数 * 数据库设计 * 安装Python依赖 * 运行应用 * 前端代码修改 * 测试前端界面 * 测试数据生成 * 功能测试 * Bug修复 * 总结 在上一篇《Cursor AI编程助手不完全指南》中,我们详细介绍了Cursor这款强大的AI编程工具。为了让大家能更直观地了解 Cursor 的实战应用价值,本文将通过一个实际项目来展示其开发流程。我们将使用 Cursor 开发一个 Web 版单词学习程序,通过这个案例,您将看到 AI 辅助开发的完整过程,体验从需求分析到代码实现的全过程。让我们开始这次实战之旅。 需求分析 在开始开发之前,明确的需求文档是项目成功的关键。一个好的需求文档不仅能指导开发方向,还能作为与 Cursor 进行高效对话的重要基础。我们有两种方式来准备需求文档:自行编写需求文档和借助 Cursor 生成需求文档