web worker 内部应封装轻量事件总线替代硬编码 onmessage,通过 emit/on 统一触发和监听语义化事件(如 'io:read-chunk'),支持异步生命周期通知、降低主线程耦合、提升可测性与复用性。

在 Web Worker 内部封装事件触发器,不是为了模拟 DOM 事件系统,而是构建一种轻量、解耦、可组合的任务响应机制——它让 Worker 不再是“一问一答”的被动执行体,而能主动通知状态变化、分阶段反馈进度、甚至广播异常或中断信号。这种设计显著提升主线程与 Worker 协作的清晰度和可控性,尤其适合长时任务(如大文件解析、流式加密、渐进式渲染)。
用自定义事件总线替代硬编码 onmessage
直接在 self.onmessage 里写业务逻辑会导致 Worker 脚本臃肿、难以测试、无法复用。更清爽的做法是引入一个极简事件总线:
- Worker 启动时初始化一个 Map 存储事件名 → 回调列表
- 暴露 emit 方法用于内部触发事件(如 'progress', 'chunk-ready', 'error')
- 暴露 on 方法供外部(主线程)注册监听,通过 postMessage 将事件名和数据传回
- 主线程不再只监听 'message',而是统一处理 { type: 'event', name: 'progress', payload: ... } 结构
支持异步生命周期事件的触发
Worker 内部常需异步加载资源(如 importScripts)、等待 SharedArrayBuffer 初始化、或启动子 Worker。这时事件应能跨异步边界触发:
- 在 importScripts 完成后 emit('scripts-loaded')
- 当 Atomics.wait 返回非-timeout 状态时 emit('shared-ready')
- 避免在回调里直接调用 postMessage,改由事件总线统一分发,确保顺序与语义一致
用事件类型区分通信意图,降低耦合
主线程向 Worker 发送消息时,不应只传原始数据,而应携带明确语义的 type 字段;Worker 内部据此 emit 对应事件,而非混用 if-else 分支:
- 主线程发送:{ type: 'start-parse', fileHandle: ... }
- Worker 解析后 emit('parse-started') → 主线程更新 UI 状态
- 每处理 10MB emit('parse-progress') → 主线程更新进度条
- 完成时 emit('parse-completed') → 主线程触发下载或渲染
- 出错时 emit('parse-error', error) → 主线程展示友好提示并清理资源
事件命名遵循语义化 + 作用域前缀
避免事件名冲突和歧义,推荐格式为 domain:verb-noun:
- 'io:read-chunk'、'crypto:encrypt-block'、'csv:row-parsed'
- 主线程可选择性监听,比如只关心 'io:*' 表示所有 I/O 相关进展
- Worker 内部可通过正则匹配批量注册监听器,便于调试和审计











