Web Worker 必须分离为独立 .js 文件且通过 HTTP/HTTPS 加载,file:// 协议下必然失败;通信依赖 postMessage/onmessage,需注意监听时机、Transferable 零拷贝及错误双重捕获。

Web Worker 不能写在 HTML 里,必须拆成独立 .js 文件;本地双击打开的 file:// 页面必然失败,必须走 HTTP/HTTPS 服务。
new Worker() 路径报错:Failed to construct 'Worker'
这是最常卡住的第一步。错误本质是浏览器拒绝加载非同源、不可 fetch 的脚本路径。
-
file://协议下直接双击 HTML —— 报Script at 'file:///' cannot be accessed from origin 'null';必须用npx http-server、VS Code Live Server 或任意本地服务启动 - 相对路径如
'./worker.js'在 Vite/Webpack 等构建环境下可能解析失败;ESM 项目中唯一稳的写法是new Worker(new URL('./worker.js', import.meta.url)) - CDN 上的脚本(如
https://cdn.example.com/worker.js)即使开了 CORS 也不行 ——new Worker()强制同源,不走 CORS 流程 - 想动态生成逻辑?用
Blob构造更可靠:new Worker(URL.createObjectURL(new Blob(['self.onmessage = ...'], {type: 'application/javascript'})))
主线程发了 postMessage,Worker 却没收到
不是代码没跑,而是监听时机或绑定位置错了。Worker 通信没有“默认回调”,全靠显式注册。
- 主线程必须在
postMessage()之前设置worker.onmessage,否则第一次消息直接丢失;推荐改用worker.addEventListener('message', ...),更健壮 - Worker 文件里写了
console.log('init')不代表self.onmessage已生效 —— 必须显式写self.onmessage = function(e) { ... }或self.addEventListener('message', ...) - Worker 内部抛了未捕获异常(比如
JSON.parse失败、fetch拒绝),默认静默;加self.onerror = e => self.postMessage({type: 'error', ...})主动透传
传大数组卡顿几百毫秒,怎么避免深拷贝
结构化克隆(structured clone)对普通 Array 或 Object 是完整复制,10MB 数据就明显卡顿。关键不是“怎么传”,而是“怎么移交所有权”。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
- 只对
ArrayBuffer、TypedArray(如Uint8Array)、ImageBitmap、OffscreenCanvas和MessagePort支持transfer参数 - 主线程发送时必须把 buffer 列进第二个参数:
worker.postMessage({data}, [data.buffer]);之后data.buffer变成byteLength: 0,不能再读 - Worker 接收后直接用:
const view = new Uint8Array(e.data.data)—— 零拷贝,内存直接移交 - 误把普通数组当 transferable 传(如
[arr])不会报错,但毫无效果,仍会深拷贝
Worker 里 document.getElementById 报 ReferenceError
这不是兼容性问题,是设计限制:Worker 线程根本没有 document、window、alert、localStorage、setTimeout(等等,setTimeout 其实有,但 localStorage 真没有)。
- 所有 DOM 操作必须由主线程完成;Worker 只负责纯计算 —— 解析 JSON、加密、排序、图像像素处理、音频 FFT
- 结果通过
postMessage()传回,主线程再调用document.getElementById().innerText = ... - 能用的 API 很有限:
self、fetch(注意部分浏览器需self.fetch)、IndexedDB、atob/btoa、WebAssembly、SharedArrayBuffer(需跨域隔离)
真正容易被忽略的,是 transfer 后主线程变量的“静默失效”——它不会报错,只是突然读不到数据;还有 error 事件的双重兜底:Worker 内要 self.onerror,主线程也要 worker.onerror,缺一不可。

















