Web Workers 是 JavaScript 的后台线程机制,通过 postMessage/onmessage 通信,数据经结构化克隆传递;专用 Worker 用 new Worker() 创建,SharedWorker 支持多页面共享;不可访问 DOM,仅限可序列化数据与特定 Transferable 类型。

JavaScript 本身是单线程的,Web Workers 不是让 JS 变成多线程语言,而是提供一种在后台线程运行脚本的机制——主线程不阻塞,计算任务被卸载到独立的、与主线程内存隔离的 Worker 实例中。
Web Workers 怎么创建和通信?
Worker 必须从外部 JS 文件启动,不能内联;主线程和 Worker 之间只能通过 postMessage() 和 onmessage 传递消息(序列化拷贝,不是共享内存)。
-
new Worker('path/to/worker.js')创建专用 Worker;new SharedWorker(...)支持多页面共享(但通信更复杂) - 传参只能是可序列化的值(
JSON.stringify能处理的),function、undefined、RegExp、Date(部分环境)、Map/Set(需手动转换)都会丢失或报错 - Worker 内部不能访问
window、document、localStorage等 DOM 相关 API,但可以使用fetch、setTimeout、WebAssembly、IndexedDB
/* main.js */
const worker = new Worker('calc.js');
worker.postMessage({ data: [1, 2, 3, 4, 5], op: 'sum' });
worker.onmessage = (e) => console.log('Result:', e.data); // Result: 15
/ calc.js /
self.onmessage = (e) => {
const { data, op } = e.data;
let result = op === 'sum' ? data.reduce((a, b) => a + b, 0) : 0;
self.postMessage(result);
};
为什么不能直接共享变量或调用函数?
因为 Worker 运行在完全独立的执行上下文里:有自己的 self(不是 window),没有事件循环共享,也没有引用传递能力。所谓“多线程”只是并发(concurrent),不是并行(parallel)意义上的内存共享线程。
- 试图在 Worker 中读取主线程的
let x = 42—— 报错:ReferenceError: x is not defined - 传一个对象进去,修改它的属性 —— 主线程原对象不会变,因为是结构化克隆(structured clone),不是引用
- 想用
Transferable避免拷贝开销?可以,但仅限ArrayBuffer、MessagePort、ImageBitmap等少数类型,且转移后原端自动失效
哪些场景适合用 Web Workers?
适合 CPU 密集型、可拆解、无 DOM 依赖的任务。不适合频繁小数据交互或需要实时 DOM 更新的逻辑。
立即学习“Java免费学习笔记(深入)”;
- 图像处理(Canvas 像素遍历、滤镜计算)
- 大数据排序/搜索(如前端本地日志分析)
- 加密解密、哈希计算(
SubtleCrypto在 Worker 中可用) - 解析大型 JSON 或 CSV(配合
stream+TextDecoder分块处理) - 避免
while(true)或长循环导致页面卡死(但注意:Worker 本身也会卡死自己的线程,需合理分片+setTimeout或requestIdleCallback让出控制权)
真正容易被忽略的是错误边界:Worker 内的未捕获异常不会冒泡到主线程,也不会触发 window.onerror;必须显式监听 worker.onerror 或在 Worker 内用 try/catch + postMessage 上报。还有,Worker 脚本路径受同源限制,跨域会静默失败。











