Web Worker 异常不会自动冒泡到主线程,必须显式捕获并上报:Worker 内用 self.onerror 和 unhandledrejection 监听错误,通过 postMessage 发送;主线程监听 onmessage 解析 type 字段处理 error,不可依赖 worker.onerror 或同步等待。

Web Worker 的异常不会自动“冒泡”到主线程,它天然隔离,错误只停留在 Worker 内部;父子线程之间也没有同步执行关系——它们是并行、异步通信的。想让主线程感知 Worker 异常,必须显式捕获并主动上报。
Worker 内部要主动捕获并上报错误
Worker 脚本里任何未捕获的同步或异步错误(比如 throw new Error()、Promise rejection、定时器回调出错),默认只会终止当前 Worker,主线程完全不知情。必须手动监听 + 转发:
- 用
self.onerror捕获同步错误(如语法错、运行时报错) - 用
self.addEventListener('unhandledrejection', ...)捕获未处理的 Promise 错误 - 所有捕获到的错误,都通过
self.postMessage({ type: 'error', payload: error })发送给主线程 - 避免在 Worker 中直接
console.error—— 主线程看不到,也无日志聚合能力
主线程需监听 Worker 的 error 事件和自定义消息
Worker 实例本身有 onerror,但它只响应 Worker 初始化失败(如脚本加载 404、语法解析失败),不响应运行时逻辑错误。真正可靠的方案是:
- 主线程注册
worker.onmessage,统一解析消息体中的type字段:区分'result'和'error' - 对
'error'类型消息做降级处理:提示用户、重试、关闭 Worker、上报监控系统 - 不要依赖
worker.onerror做业务错误兜底——它覆盖范围窄,容易漏掉关键逻辑异常
父子线程不存在“同步等待”,要用消息驱动建模
主线程调用 worker.postMessage() 后立即返回,不等 Worker 执行完;Worker 调用 self.postMessage() 也是异步发送。所谓“同步”,只能靠业务层约定实现:
- 给每个请求加唯一
id,Worker 返回时带上该id,主线程用 Map 缓存 pending 请求,按 id 匹配响应 - 超时控制必须由主线程发起:用
setTimeout监控某次 postMessage 是否在预期时间内收到 reply - 禁止在主线程中写
while(!done) {}等待 Worker —— 这会阻塞 UI,违背使用 Worker 的初衷
注意异步错误的特殊性:Promise reject 不会中断 Worker,但也不自动上报
Worker 中 Promise.reject() 如果没被 .catch(),会触发 unhandledrejection 事件,但不会终止 Worker(除非启用了 self.addEventListener('unhandledrejection', e => e.preventDefault()))。关键点:
- 必须显式监听
unhandledrejection并转发错误,否则主线程永远收不到 - 不能指望
try/catch包裹await就万事大吉——如果忘了catch或.catch(),错误就静默丢失 - 推荐封装一个
safePostMessage(data, error?)工具函数,在 Worker 内统一处理成功/失败路径

















