async函数报错不会自动冒泡,必须在顶层入口显式try-catch并结构化记录日志,辅以unhandledrejection全局监听,确保错误可追溯、可分级上报。

async 函数报错不会自动冒泡到全局,必须主动捕获并结构化记录,否则容易静默失败、排查困难。
顶层调用处显式 try-catch
不要指望 async 函数体外自动捕获内部 await 抛出的错误——它只对同步错误或 await 后立即 reject 有效。真正可靠的做法,是在每个用户可触发的顶层入口(如按钮点击、API 调用、路由守卫)加 try-catch:
- 捕获 error.stack,保留原始调用链信息
- 记录关键上下文:函数名、简要参数(如 userId: 'u_abc123'、action: 'submit-order')、环境(env: 'prod')
- 避免空 catch 或仅 console.error,必须走统一日志通道
监听 unhandledrejection 兜底
即使写了 try-catch,仍可能漏掉未 await 的 Promise 或被忽略的 .catch()。用全局监听补位:
- window.addEventListener('unhandledrejection', e => { logError(e.reason, { type: 'unhandled-rejection' }); });
- 注意:e.reason 可能是 Error 实例,也可能是普通值(如字符串、对象),需兼容处理
- 该事件仅捕获未被任何 .catch() 或 try-catch 拦截的 Promise reject
日志内容要结构化、可追溯
光记 error.message 没用,得让日志能串联起“谁、在哪儿、干了什么、出了什么错”:
- errorId:生成唯一 UUID,前后端联查时用
- context:含文件名+行号(fileName: 'user.js:42')、触发动作、用户标识哈希、环境
- stack:保留完整堆栈,但可截断过长路径或过滤敏感目录(如 /node_modules/)
- type:标记错误来源('fetch-fail'、'parse-error'、'timeout')
按影响分级上报,避免日志泛滥
不是所有错误都值得实时告警,要区分对待:
- 网络类失败(如 fetch 超时、503)→ 记录 + 聚合统计,不触发告警
- 运行时异常(Cannot read property 'x' of undefined)→ error 级,计入错误率看板
- 业务校验拒绝(后端返回 { code: 'INVALID_EMAIL' })→ warn 级,用于优化表单体验
- 同一 errorId 5 分钟内重复出现 ≥3 次 → 触发采样快照或降级提示











