Web Workers 不能直接操作 DOM,只能通过 postMessage 通信,需单独 JS 文件、同源路径,注意 MIME 类型和模块类型配置,Dedicated Worker 适用于 CPU 密集任务。

Web Workers 不能直接操作 DOM
这是最常踩的坑:Worker 线程里调用 document.getElementById 或 console.log(非 self.console.log)会报错,因为 Worker 没有 window、document、localStorage 等主线程专属对象。
Worker 只能访问:self、fetch、setTimeout、IndexedDB、WebAssembly 和部分加密 API。所有通信必须通过 postMessage 和 onmessage 进行。
- 主线程发消息用:
worker.postMessage(data),支持结构化克隆(可传对象、数组、ArrayBuffer,但不能传函数或 DOM 节点) - Worker 收消息写在
self.onmessage = (e) => { ... }里,e.data是传入数据 - Worker 主动发回结果也用
self.postMessage(result),主线程监听worker.onmessage
如何正确创建和使用 Dedicated Worker
必须把 Worker 逻辑写在**单独的 .js 文件里**,不能是内联字符串或箭头函数——浏览器会拒绝执行。
例如,新建 worker.js:
立即学习“Java免费学习笔记(深入)”;
self.onmessage = function(e) {
const result = e.data * e.data;
self.postMessage(result);
};主线程中加载它:
const worker = new Worker('worker.js');
worker.postMessage(123);
worker.onmessage = function(e) {
console.log('计算结果:', e.data); // 15129
};- 路径必须是同源的,不支持
file://协议(本地双击打开会失败,需起本地服务) - Worker 实例可复用,但每个
new Worker()都是独立线程,频繁创建销毁开销大 - 记得在不需要时调用
worker.terminate(),否则线程持续占用内存
遇到 “Uncaught DOMException: Failed to construct ‘Worker’” 怎么办
这个错误几乎都源于跨域或 MIME 类型问题。常见原因:
- Worker 脚本返回了
text/html(比如 404 页面被当成 JS 加载)→ 检查路径是否拼错,服务器是否返回了正确的Content-Type: application/javascript - 用了
importScripts('xxx.js')但路径不对或跨域 → 所有importScripts的资源也必须同源且可访问 - 在模块 Worker 中用了
type: "module",但没加type="module"到new Worker()构造函数:new Worker('worker.js', { type: 'module' }) - Vite / Webpack 项目中直接写
new Worker('./worker.js')会失败 —— 需用new Worker(new URL('./worker.js', import.meta.url))让打包器识别并处理
SharedWorker 和 ServiceWorker 不是“更高级的多线程”
别被名字误导:SharedWorker 是为多个页面/iframe 共享一个后台线程设计的,不是为了提升单页性能;ServiceWorker 是网络代理 + 缓存控制器,生命周期由浏览器管理,不能手动 postMessage 触发任意计算。
真要 CPU 密集型任务(如图像处理、JSON 解析、加密),只用 DedicatedWorker。如果需要线程池,得自己封装管理多个 Worker 实例,注意避免同时创建过多导致浏览器限制(Chrome 通常限制约 20 个 Worker)。
另外,Worker 启动本身有毫秒级延迟,简单计算(比如











