web worker 专注纯计算任务,service worker 负责网络与缓存,二者通过主线程中转消息实现分层解耦协作;典型流程为:主线程判别“算”或“取”,分别交由 worker 或 sw 处理,并在必要时持久化结果。

Web Worker 和 Service Worker 各自独立运行,不能直接调用或共享作用域,但可以通过合理分工与消息协作,共同支撑复杂异步任务流。关键不在于“合并使用”,而在于“分层解耦”:一个专注计算,一个专注网络与缓存。
职责必须清晰划分
Web Worker 负责纯计算类任务,比如解析大文件、加密解密、图像滤镜运算、JSON 数据聚合等——它不接触网络请求,也不操作缓存 API;Service Worker 则只处理 fetch 事件、缓存策略、离线资源管理、推送通知等——它不执行 CPU 密集型逻辑,也不持有业务数据结构。
- 主线程发起任务时,先判断性质:是“算”还是“取”?
- 需要读取/写入远程资源 → 交由 Service Worker 拦截并返回(可能来自 cache 或 network)
- 拿到数据后需大量加工 → 转发给 Web Worker 处理,避免阻塞渲染
- 处理结果若需持久化 → 主线程再调用 IndexedDB 或通过 Service Worker 缓存静态产物(如生成的图表 blob)
通信链路要可控且可追溯
两者都只能和主线程通信,无法直连。因此主线程是协调枢纽,需主动中转消息,并做好类型校验与错误兜底。
- 主线程用
worker.postMessage()向 Web Worker 发送原始数据或指令 - Web Worker 完成后,用
self.postMessage()把结果(仅支持结构化克隆的数据)回传 - 主线程收到结果,再决定是否触发
fetch()—— 此时 Service Worker 自动介入,按预设策略响应 - 若需将 Worker 输出存为离线资源,主线程可构造 Blob URL,再用
cache.put()(在 Service Worker 内部调用)存入 Cache Storage
典型协同场景示例
比如一个离线优先的报表系统:
- 用户点击“生成年度汇总” → 主线程从 IndexedDB 读取原始记录(或让 Service Worker 返回缓存的 JSON)
- 主线程把数据数组发给 Web Worker 做分组、统计、排序
- Worker 返回聚合结果后,主线程渲染图表,并生成 PNG canvas 数据
- 主线程创建 Blob,触发一次
fetch('/report.png'),Service Worker 捕获该请求,将 Blob 存入 cache 并返回,实现后续离线访问
避开常见陷阱
协同失效往往不是技术不可行,而是设计越界:
- 不要在 Web Worker 里调用
fetch—— 它没有 fetch 权限,且违背“计算归 Worker、网络归 SW”的分层原则 - 不要在 Service Worker 中做循环遍历万级数组 —— 它有执行时长限制(通常 50–60ms),容易被终止
- 避免主线程频繁发送小消息给 Worker —— 高频 postMessage 会带来序列化开销,应批量传递或使用 Transferable(如 ArrayBuffer)提升效率
- Service Worker 更新后,旧缓存不会自动清理 —— 需在
activate阶段手动cache.keys()清理过期版本











