可将重复的try...catch逻辑抽成高阶函数safeRun,统一处理错误并支持同步/异步,再按UI层、API层、工具层定制封装,结合上下文增强错误信息,同时避免过度封装以保持可调试性。

可以把重复的 try...catch 逻辑抽成一个高阶函数,用它包裹业务代码,统一处理错误(比如打日志、提示用户、降级返回),让业务层专注核心逻辑,不写样板错误处理。
封装基础执行函数:接收函数并自动捕获异常
定义一个通用函数,比如 safeRun,它接受一个函数和可选配置(如错误回调、默认返回值):
- 执行传入函数,成功时返回结果;失败时捕获
Error,不抛出,而是交由配置的onError处理 - 支持同步和
async函数(内部用await+try/catch判断) - 示例:
<!-- JavaScript -->function safeRun(fn, { onError = console.error, fallback = null } = {}) { return async (...args) => { try { const result = fn(...args); return result instanceof Promise ? await result : result; } catch (err) { onError(err); return fallback; } }; }
按场景定制封装:区分 UI 层、API 层、工具层
不同位置对错误的响应方式不同,可基于 safeRun 衍生专用函数:
-
API 请求封装:自动重试、添加请求 ID、上报监控、转为标准响应格式(如
{ data: null, error: xxx }) -
React 事件处理:防止因点击等触发异常导致组件崩溃,用
safeHandle包裹onClick等回调,错误时仅警告不打断交互 -
工具函数兜底:如
safeParseJSON、safeGet,失败返回undefined或默认值,不抛错
结合上下文增强错误信息:注入来源与元数据
单纯捕获错误不够,需知道“谁、在哪、为什么”出错。可在封装时自动附加:
- 调用位置(
new Error().stack截取前几行,或用console.trace辅助定位) - 业务上下文,例如 API 封装中加入
url、method、params(脱敏后) - 环境标识(
process.env.NODE_ENV、是否移动端)便于归类分析
避免过度封装:保持可调试性与可控性
统一封装不等于隐藏所有细节:
- 保留原始错误对象的引用(如将
err.original = originalErr),方便调试时展开 - 提供「绕过封装」的显式调用方式(如
unsafeRun(fn)),供测试或特殊逻辑使用 - 不拦截
console.error或全局window.onerror,它们应作为兜底,而非替代

















