javascript异步错误处理需确保错误不丢失、上下文可追溯、格式标准化:分别监听浏览器unhandledrejection和node.js unhandledrejection事件,封装safeasync等工具拦截错误,统一日志字段(level/timestamp/message/stack等),清洗堆栈,用sendbeacon或https.request上报并缓存重试。

在 JavaScript 异步错误处理中,要把异步错误统一收集并格式化到日志系统,关键不是“捕获所有错误”,而是确保错误不丢失、上下文可追溯、格式可标准化。浏览器和 Node.js 环境的机制不同,需分别应对,再统一输出结构。
捕获未处理的 Promise 拒绝
Promise 链中未被 .catch() 或 try/catch 捕获的 rejection 会触发全局事件,这是统一日志的第一道防线:
- 浏览器中监听
unhandledrejection事件,从event.reason获取错误对象(可能是 Error 实例,也可能是原始值) - Node.js 中监听
process.on('unhandledRejection'),注意它不会自动终止进程,但必须显式处理,否则下次版本可能抛出异常 - ⚠️ 注意:
event.reason不总是 Error 实例,需用instanceof Error判断,不是则包装成 Error,避免后续格式化失败
封装异步入口,强制错误流向日志
对定时器、事件回调、fetch、async 函数等常见异步源头做轻量封装,把错误拦截在业务层之外:
- 写一个
safeAsync工具函数,接收 async 函数或 Promise,返回一个始终 resolve 的 Promise,并在 reject 时调用日志方法 - 对
addEventListener回调、setTimeout、setInterval等,用 try/catch 包裹执行体,捕获同步抛出 + 异步内抛出(如回调里 await 失败) - 例如:
fetch(url).catch(err => logger.error('API_FAIL', { url, err }))比裸调用更可控
标准化错误日志字段与堆栈处理
统一日志格式的核心是让每个错误条目包含可筛选、可关联的最小必要信息:
- 必含字段:
level: 'error'、timestamp(Date.now())、message(err.message或String(err))、stack(优先用err.stack,降级用new Error().stack) - 增强字段:
type: err.constructor?.name、origin: 'promise-rejection' | 'fetch-error' | 'timeout'、context(由调用方传入,如页面 URL、用户 ID、请求 ID) - 堆栈需清洗:移除 node_modules 和 webpack 冗余行,保留前 5–10 行有效调用帧;浏览器中可用
stack.split('\n').slice(0, 8)简单截断
集成上报与降级策略
日志最终要发出去,但网络可能不可用,需防阻塞、防堆积、防重复:
- 使用
sendBeacon(浏览器)或https.request(Node)异步发送,不等待响应 - 内存中缓存最近 20 条错误,发送失败时暂存,下次有机会再重试(避免刷新即丢)
- 对高频错误(如 1 秒内同 message 错误超 3 次),聚合为一条并加
count: 5字段,减少日志风暴 - 敏感字段(如 token、密码)在序列化前主动过滤,用正则或白名单 key 控制
不复杂但容易忽略:格式化不是一次性的字符串拼接,而是围绕 Error 实例构建可扩展的 log 对象,再由日志 SDK 序列化传输。保持 error 对象完整,比提前 toString 更利于后期分析。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











