JavaScript 本身是单线程的,Web Workers 提供后台线程运行脚本以避免阻塞主线程,但无法操作 DOM 或访问 window、document;Dedicated Worker 一对一通信,适用于计算密集型任务;需通过 postMessage 通信,支持 transferable objects 避免大数组拷贝开销;SharedArrayBuffer + Atomics 可实现真正共享内存,但须启用跨域隔离(COOP/COEP)且仅限 HTTPS 环境。

JavaScript 本身是单线程的,Web Workers 不是让 JS 变成多线程,而是提供一种在**后台线程中运行脚本**的机制,避开主线程阻塞。它不能操作 DOM,也不能访问 window、document 等全局对象——这点必须一开始就认清。
如何创建并使用一个 Dedicated Worker
最常用的是 DedicatedWorker,一对一通信,适合处理计算密集型任务(如图像处理、加密、大数据排序)。
- Worker 脚本必须放在独立的
.js文件中,不能是内联字符串或 Blob URL(部分浏览器限制) - 主线程用
new Worker('path/to/worker.js')实例化,Worker 内部用self.onmessage接收、self.postMessage发送 - 通信内容会自动序列化(结构化克隆算法),不支持函数、undefined、Promise、DOM 节点等
/* main.js */
const worker = new Worker('calc-worker.js');
worker.postMessage({ numbers: [1, 2, 3, 4, 5] });
worker.onmessage = function(e) {
console.log('Result:', e.data); // { sum: 15 }
};
/ calc-worker.js /
self.onmessage = function(e) {
const sum = e.data.numbers.reduce((a, b) => a + b, 0);
self.postMessage({ sum });
};
为什么 postMessage 传大数组会卡顿?
因为默认走结构化克隆,对大对象(比如几 MB 的 ArrayBuffer 或嵌套深的 JSON)复制开销高。这时候要用 transferable objects 避免拷贝。
- 只支持
ArrayBuffer、MessagePort、ImageBitmap等少数类型 - 转移后原主线程的引用立即失效(变成
null),内存所有权交给 Worker - 写法是
postMessage(data, [buffer]),第二个参数是 transfer list
/* 主线程 */ const buffer = new ArrayBuffer(1024 * 1024); const view = new Uint8Array(buffer); view.fill(1);worker.postMessage({ data: buffer }, [buffer]); // ← 关键:转移
立即学习“Java免费学习笔记(深入)”;
/ Worker 内 / self.onmessage = function(e) { const view = new Uint8Array(e.data.data); // 直接读,不拷贝 };
SharedArrayBuffer + Atomics 能否真正共享内存?
可以,但有严格前提:必须启用跨域隔离(COOP/COEP 头),且现代浏览器默认禁用,仅限 HTTPS + 显式声明场景。
-
SharedArrayBuffer是一块可被多个线程直接读写的内存区域 -
Atomics提供原子操作(如Atomics.add()、Atomics.wait()),避免竞态 - 不加
Atomics直接读写仍是未定义行为,不是“线程安全”的捷径
没配好 COOP/COEP 时,控制台会报错:SharedArrayBuffer is not defined 或 Atomics is not defined —— 别硬试,先检查响应头是否含 Cross-Origin-Embedder-Policy: require-corp 和 Cross-Origin-Opener-Policy: same-origin。
真正难的从来不是调用 new Worker(),而是判断该不该用、数据怎么传、错误怎么捕获(worker.onerror 不会冒泡)、以及调试时看不到 Worker 中的 console 输出(得用 chrome://inspect 单独连)。











