Skip to content

Web Workers API

Web Workers 是浏览器把 JavaScript 搬到主线程之外的后台线程运行的标准机制:worker 有独立的全局作用域(selfWorkerGlobalScope)、独立的事件循环,与主线程之间只能靠 postMessage 传消息(结构化克隆拷贝,或 Transferable 零拷贝移交),不共享变量、也碰不到 DOM。规范上它属于 WHATWG HTML 现行标准的「Web workers」章——基础的专用 Worker(Dedicated)自 2015 年起就是 Baseline,{ type: "module" } 模块 worker 随 Firefox 114(2023 中)补齐而进入 Baseline,SharedWorker(多页共享单实例)与 OffscreenCanvas(把 canvas 渲染卸到 worker)也已在主流浏览器落地。本叶专注浏览器 Worker 的编程面:三类 worker 的定位、postMessage 心智模型、双向通信与错误处理、数据传输与所有权移交、以及 Comlink 把裸消息收发变成 async 调用的工程模式。

边界:WASM 在 worker 里跑只在需要时点一句、深入见 WebAssembly 叶Service Worker 是一种「特殊 worker」(网络代理 + 生命周期),本叶只在对比时点到,完整生命周期见 Service Worker 与 PWA 叶

评价

优点

  • 真并行,主线程不阻塞:把加解密、图像/音视频处理、大 JSON 解析、物理/布局计算等 CPU 密集活挪进 worker,主线程专心响应输入与渲染,60fps 不掉帧——这是 worker 唯一但决定性的价值
  • 隔离干净、心智简单:worker 无共享内存(SharedArrayBuffer 除外)、无锁、无数据竞争,一切靠消息传递,比多数语言的线程模型好写得多
  • 传大数据可零拷贝ArrayBufferOffscreenCanvasImageBitmap 等 Transferable 对象能移交所有权而非深拷贝,几十 MB 缓冲区跨线程近乎免费
  • 能力可观:worker 内有 fetchWebSocketIndexedDBWebAssemblyOffscreenCanvas、Streams、Cache 等——足以承载完整的数据层与渲染层,只是没有 DOM
  • 有共享与卸载两张王牌SharedWorker 让多个标签页共用一个后台实例(单一 WebSocket、统一状态),OffscreenCanvas 把 WebGL/2D 渲染整个搬进 worker

局限

  • 通信有成本、有边界postMessage 走结构化克隆——函数、DOM 节点、类的方法都传不过去DataCloneError);大对象深拷贝本身也耗时,不是所有活都值得下放
  • 启动不是免费的:新建 worker 要下载并解析脚本、建独立上下文,冷启动几毫秒到几十毫秒;短平快的小任务下放反而更慢
  • 裸 API 样板重postMessage + onmessage + 手工 switch(type) 路由 + 手工关联请求响应,写多了又臭又长——工程上几乎必配 Comlink 这类 RPC 封装
  • 共享内存门槛高SharedArrayBuffer 需要页面发送 COOP + COEP 两个响应头(Spectre 缓解后的硬门槛),部署不满足就用不了
  • SharedWorker 兼容性参差:桌面主流支持,但 Firefox 不支持 { type: "module" } 的 SharedWorker,移动端支持也有限——用前必须验目标环境

一句话选型:页面上有一段会「卡住」用户的同步 JS 计算,就把它挪进 Worker;要在多标签页间共享一条长连接/一份状态用 SharedWorker;要把复杂图形渲染搬离主线程用 OffscreenCanvas;一旦通信超过三五条消息,就上 Comlink 把它变成普通 async 函数调用。反过来,只是想「延后执行」而非「并行计算」,setTimeoutrequestIdleCallback 就够,别为它付 worker 的启动与通信税。

本叶地图

  • 入门 —— 三类 worker(Dedicated/Shared/Service)定位与选择、postMessage 心智模型(消息传递而非共享内存)、「主线程不阻塞」到底意味着什么、何时用与何时别用
  • 专用 Worker —— new Worker 构造、经典 vs 模块 worker(type: "module"importScripts)、双向 postMessageonmessage、结构化克隆传值、onerrormessageerror 错误处理、terminate()self.close()、worker 内可用的 API 范围
  • 共享 Worker —— SharedWorkeronconnectMessagePortport.start()、多页多标签共享单实例、chrome://inspect 调试、Comlink 配 port 用法、Firefox 对 module SharedWorker 的限制
  • 数据传输与 OffscreenCanvas —— 结构化克隆 vs Transferable 所有权移交(转移后原对象 detached)、可转移类型清单、SharedArrayBuffer 与 COOP/COEP 头、OffscreenCanvas 把渲染卸到 worker、ImageBitmap
  • 工程模式与 Comlink —— 裸 postMessage 样板痛点、Comlink 用 Proxy 把 worker 调用变 async 函数、自动处理 transferable、worker 池模式、Vite 的 new Worker(new URL(...), { type: "module" }) 导入、何时不值得下放
  • 参考 —— 三类 worker 对比表、Worker API 速查、可转移类型表、结构化克隆 vs transfer 对比、worker 内可用/不可用 API、易错点清单、资源链接

文档地址

MDN Web Workers API

GitHub 地址

whatwg/html(HTML 现行标准仓库,「Web workers」章为规范原文)

幻灯片地址

Web Workers API

测试题

Web Workers API 测试题