Web Workers 是 JavaScript 的后台线程机制,通过 postMessage/onmessage 通信,数据经结构化克隆传递;专用 Worker 用 new Worker() 创建,SharedWorker 支持多页面共享;不可访问 DOM,仅限可序列化数据与特定 Transferable 类型。
JavaScript 本身是单线程的,Web Workers 不是让 JS 变成多线程语言,而是提供一种在后台线程运行脚本的机制——主线程不阻塞,计算任务被卸载到独立的、与主线程内存隔离的 Worker 实例中。
Worker 必须从外部 JS 文件启动,不能内联;主线程和 Worker 之间只能通过 postMessage() 和 onmessage 传递消息(序列化拷贝,不是共享内存)。
new Worker('path/to/worker.js') 创建专用 Worker;new SharedWorker(...) 支持多页面共享(但通信更复杂)JSON.string
ify 能处理的),function、undefined、RegExp、Date(部分环境)、Map/Set(需手动转换)都会丢失或报错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)意义上的内存共享线程。
let x = 42 —— 报错:ReferenceError: x is not defined
Transferable 避免拷贝开销?可以,但仅限 ArrayBuffer、MessagePort、ImageBitmap 等少数类型,且转移后原端自动失效适合 CPU 密集型、可拆解、无 DOM 依赖的任务。不适合频繁小数据交互或需要实时 DOM 更新的逻辑。
SubtleCrypto 在 Worker 中可用)stream + TextDecoder 分块处理)while(true) 或长循环导致页面卡死(但注意:Worker 本身也会卡死自己的线程,需合理分片+setTimeout 或 requestIdleCallback 让出控制权)真正容易被忽略的是错误边界:Worker 内的未捕获异常不会冒泡到主线程,也不会触发 window.onerror;必须显式监听 worker.onerror 或在 Worker 内用 try/catch + postMessage 上报。还有,Worker 脚本路径受同源限制,跨域会静默失败。