Web Worker 的未处理异常必须在 Worker 内通过 self.addEventListener('error') 或 self.onerror 捕获,并配合 self.addEventListener('unhandledrejection') 处理 Promise 拒绝;主线程需监听 worker.onmessage 和 worker.onerror 实现完整可观测性。

Web Worker 内部的未处理异常无法被主线程的 window.onerror 捕获,必须在 Worker 自身线程中注册监听器,并主动将结构化错误信息发回主线程——这是实现可观测性的唯一可靠路径。
Worker 线程内必须注册 self.addEventListener('error')
Worker 运行在独立全局上下文,self 是其等价于主线程 window 的对象。所有未捕获的同步错误(如 ReferenceError)、脚本加载失败(importScripts 报错)、运行时异常,都需通过以下方式之一捕获:
-
self.addEventListener('error', e => { ... })—— 推荐写法,语义清晰,支持e.preventDefault()阻止控制台默认打印 -
self.onerror = (message, filename, lineno, colno, error) => { ... }—— 兼容性好,接收标准五参数
注意:仅靠 onerror 不足以覆盖全部场景,还需补充其他监听器。
必须显式监听 unhandledrejection
Promise 拒绝属于“静默错误”,不会触发 self.onerror。若 Worker 中有未 .catch() 的 Promise.reject(),错误将完全丢失:
- 必须手动注册:
self.addEventListener('unhandledrejection', e => { self.postMessage({ type: 'worker-unhandled-rejection', reason: e.reason }); }) - 该事件不默认启用,漏掉即等于放弃捕获异步拒绝链中的错误
主线程要接收并安全处理上报消息
Worker 不能直接触发主线程的错误事件,但可通过 postMessage 主动通知。主线程需做两层防护:
- 监听
worker.onmessage,解析event.data.type区分业务消息与错误消息,再做日志、告警或降级 - 同时绑定
worker.onerror,用于捕获 Worker 初始化阶段的底层失败(如脚本 404、CORS 错误、语法错误导致创建失败)
示例:主线程中可统一记录为 console.error('[Worker Error]', data),避免混入普通日志流。
避开常见陷阱
这些情况容易导致错误“看似没发生”,实则被忽略或拦截失败:
-
importScripts()加载失败会触发self.onerror,但如果脚本本身含语法错误,Worker 创建即失败,此时只有worker.onerror能捕获 -
postMessage传入函数、undefined或循环引用对象,会触发messageerror事件,需额外监听:self.addEventListener('messageerror', e => { ... }) - 仅依赖 DevTools 的 Console 输出 ≠ 错误捕获,不能替代事件监听机制

















