web worker 与 service worker 是分工协作关系:worker 专责后台计算,service worker 负责网络代理与资源调度,主线程协调二者并管理 ui 和数据流转,三者通过 postmessage 安全通信,不可越界调用 api。

Web Worker 和离线存储机制(如 Service Worker + Cache API + IndexedDB)不是替代关系,而是分工协作的组合。Worker 负责后台计算,Service Worker 负责网络代理与资源调度,两者可共存并协同提升离线体验——关键在于明确边界、避免职责重叠、建立安全通信通道。
职责划分:谁该做什么
清晰界定各模块职责是集成设计的第一步:
- Web Worker:只处理纯计算任务(如数据解析、加密解密、图像处理、大型表单校验),不接触 DOM、不发起 fetch 请求、不操作缓存或数据库
- Service Worker:专注网络层控制——拦截 fetch、管理 Cache API、触发 Background Sync、协调 IndexedDB 同步时机
- 主线程:负责 UI 渲染、用户交互、协调 Worker 与 Service Worker 的数据流转(例如把待处理数据发给 Worker,再将结果存入 IndexedDB)
通信链路:安全高效的数据传递
三者之间需通过标准化消息机制交换数据,避免直接共享状态:
- 主线程 ↔ Web Worker:使用
postMessage()传递结构化数据(支持 ArrayBuffer、Transferable),禁止传函数或 DOM 节点 - 主线程 ↔ Service Worker:通过
navigator.serviceWorker.controller.postMessage()发送指令(如“触发离线同步”),SW 用self.addEventListener('message', ...)接收 - Web Worker ↔ Service Worker:不可直接通信,必须经主线程中转;Worker 完成计算后,由主线程决定是否调用
caches.open()存缓存,或写入 IndexedDB
离线场景下的典型协作流程
以“用户编辑文档后离线提交”为例:
- 用户在无网状态下编辑长文本 → 主线程将内容存入 IndexedDB(本地持久化)
- 主线程启动 Web Worker 对文本做语法检查/格式转换(耗时操作不卡 UI)
- Worker 返回校验结果 → 主线程更新 IndexedDB 中的文档状态
- 网络恢复时,Service Worker 拦截同步请求 → 触发 Background Sync → 主线程从 IndexedDB 读取待提交数据 → 交由 Worker 做签名或压缩 → 最终通过 fetch 发送到服务端
构建注意事项
实际集成中需规避几个常见陷阱:
- 不要在 Web Worker 中调用
fetch或caches—— 这些 API 不在 Worker 全局作用域内(除非是 Service Worker 自身) - IndexedDB 可在主线程和 Worker 中使用(需显式打开),但同一数据库不能跨线程并发写入,建议主线程统一管理写操作
- Service Worker 的
fetch事件中禁止调用postMessage给主线程(异步上下文限制),需改用clients.matchAll()+client.postMessage() - 缓存版本需与应用逻辑解耦:Cache API 的 key(如
'docs-v2')应随数据模型变更而更新,而非随 Worker 脚本版本联动











