关于请求封装中关于错误提示的三种实践方案:UI 直出 vs 全局 Handler vs EventBus

🛠️ React 项目中接口错误提示的三种实践方案:UI 直出 vs 全局 Handler vs EventBus

在实际开发中,我们经常需要在请求失败时展示统一的错误提示。无论是 axios、fetch,只要涉及封装请求,就绕不开"请求错误如何提示用户"的话题。

本文基于本人项目实战,梳理了三种常见实现方案,从简单到高级一应俱全,供你按需选用。


✅ 场景说明

  • 使用 React(任意框架均可类比)
  • 使用 axios 封装请求
  • 错误码中有业务错误(如 code: 1,而非 HTTP 错误)
  • 希望在请求失败时展示 toast 或其他提示

🔧 三种方案概览

方案 简介 优点 缺点 适用项目
方案一 直接在 axios 中调用 UI 快速简单 UI 耦合严重,不易维护 demo、PoC、小项目
方案二 抽出全局 UI handler 注入 UI 解耦、可控性强 初始化要求高 中小项目
方案三 使用 EventBus 派发事件 最灵活、可统一处理复杂错误码 代码复杂度略高 中大型项目、多人协作项目

🚀 方案一:直接调用 UI 组件(耦合强)

✅ 示例代码

javascript 复制代码
import axios from 'axios'
import { message } from 'antd'

const request = axios.create()

request.interceptors.response.use(
  res => {
    if (res.data.code !== 0) {
      message.error(res.data.message || '请求失败')
      return Promise.reject(res.data)
    }
    return res.data
  },
  err => {
    message.error(err.message || '网络错误')
    return Promise.reject(err)
  }
)

✅ 优点

  • 上手快,适合小项目
  • 没有额外封装成本

❌ 缺点

  • UI 库(如 antd、element)直接耦合进 request 层
  • 未来更换 UI 库代价大

✨ 方案二:全局 UI Handler 注入式调用(中等耦合)

✅ 核心思路

将 UI 提示通过 setUIHandler() 注入,request.ts 内只调用 handler,解耦 UI。

✅ 实现步骤

1. 定义 UI Handler 工具
javascript 复制代码
// utils/globalUI.ts
export type UIHandler = {
  error: (msg: string) => void
  success?: (msg: string) => void
}

let handler: UIHandler | null = null

export function setUIHandler(h: UIHandler) {
  handler = h
}

export function getUIHandler(): UIHandler {
  if (!handler) throw new Error('UIHandler 未初始化')
  return handler
}
2. 在 request.ts 中使用
javascript 复制代码
import axios from 'axios'
import { getUIHandler } from './globalUI'

const request = axios.create()

request.interceptors.response.use(
  res => {
    if (res.data.code !== 0) {
      getUIHandler().error(res.data.message || '请求失败')
      return Promise.reject(res.data)
    }
    return res.data
  },
  err => {
    getUIHandler().error(err.message || '网络错误')
    return Promise.reject(err)
  }
)
3. 在 App 入口注入 UI 实现
javascript 复制代码
// App.tsx
import { message } from 'antd'
import { setUIHandler } from './utils/globalUI'

setUIHandler({
  error: msg => message.error(msg),
})

✅ 优点

  • UI 解耦
  • 支持切换提示方式、mock、测试
  • 适合中型项目

❌ 缺点

  • 需要额外初始化步骤
  • 无法处理组件内自定义提示(需手动处理)

📦 方案三:基于 EventBus 的解耦提示(推荐用于复杂场景)

✅ 核心思路

  • 使用 mitt、eventemitter3 或自定义 EventBus
  • 请求失败时发送事件,由 UI 组件统一监听提示

✅ 示例实现

1. 创建事件总线
javascript 复制代码
// utils/eventBus.ts
import mitt from 'mitt'
export const eventBus = mitt<{
  showError: string
}>()
2. 请求中发出错误事件
javascript 复制代码
// request.ts
import axios from 'axios'
import { eventBus } from './eventBus'

const request = axios.create()

request.interceptors.response.use(
  res => {
    if (res.data.code !== 0) {
      eventBus.emit('showError', res.data.message || '请求失败')
      return Promise.reject(res.data)
    }
    return res.data
  },
  err => {
    eventBus.emit('showError', err.message || '网络错误')
    return Promise.reject(err)
  }
)
3. UI 层监听事件统一提示
javascript 复制代码
// GlobalErrorListener.tsx
import { useEffect } from 'react'
import { message } from 'antd'
import { eventBus } from './utils/eventBus'

export default function GlobalErrorListener() {
  useEffect(() => {
    const handler = (msg: string) => message.error(msg)
    eventBus.on('showError', handler)
    return () => eventBus.off('showError', handler)
  }, [])

  return null
}
javascript 复制代码
// App.tsx
<GlobalErrorListener />

✅ 优点

  • 完全解耦,适合复杂逻辑(如:错误码分类型处理)
  • 支持全局监听和组件级复用
  • UI 层控制力强

❌ 缺点

  • 逻辑稍复杂,需要维护事件名和事件生命周期
  • 非初学者首选

🧭 最终建议

  • 👉 小项目 / 快速原型:方案一足够
  • 👉 中型项目 / 渐进式解耦:方案二更优雅
  • 👉 大型项目 / 多人协作 / 错误分类复杂:方案三最灵活,最可控

📌 写在最后

请求错误提示并不只是简单的 toast 问题,它关系到 UI 与数据层的架构解耦程度。选对合适的方案,能让你的项目后续更稳定、好维护。

如果你觉得这篇文章对你有帮助,欢迎 👍 点赞 + 收藏,如果你有更好的实践,也欢迎评论区一起交流~

相关推荐
汉堡大王95273 分钟前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
看浪的路人5 分钟前
第9讲:大模型应用监控与可观测性——OpenTelemetry + Prometheus + Grafana 全链路追踪
java·前端·spring
内存过载6 分钟前
用表格模拟甘特图:项目排期的土办法
前端·低代码
葡萄城技术团队15 分钟前
用 SpreadJS 数据验证实现省市区三级联动
前端
派小心.38 分钟前
A/B实验分层随机种子的稳定性验证
大数据·服务器·前端·数据分析
袋鼠云数栈UED团队1 小时前
从 Skills 到可靠的 Bugfix Agent
前端
幼儿园蛋小黑1 小时前
SPI 子系统:从原理到实践
java·前端·数据库
Data analyse4561 小时前
rrweb回放事件资源加载顺序重放校验
前端·人工智能·算法·机器学习·数据分析
lexiangqicheng2 小时前
自定义表单跨端共用机制-PC设计APP渲染
java·前端·javascript
zhikouai2 小时前
AI辅助逆向工程链路:从二进制接入到等价性校验
java·linux·前端