
Web Worker 创建失败:检查 new Worker() 路径是否合法
浏览器对 Web Worker 的脚本路径有严格限制,new Worker() 只接受同源 URL(含 data: 和 Blob:),不支持直接传入内联函数或字符串代码。
- 常见错误现象:
Failed to construct 'Worker': Script at 'file:///...' cannot be accessed from origin 'null'(本地文件协议下直接双击打开 HTML) - 必须用 HTTP/HTTPS 服务启动页面,比如
npx http-server或 VS Code Live Server 插件 - 路径不能是相对路径的歧义写法,如
./worker.js在某些构建环境下可能解析失败;推荐用new Worker(new URL('./worker.js', import.meta.url))(ESM 环境下最稳) - 若 worker 脚本需动态生成,用
Blob构造更可靠:new Worker(URL.createObjectURL(new Blob(['self.onmessage = ...'], {type: 'application/javascript'})))
主线程与 Worker 通信卡住:只认 postMessage() 和 onmessage
Web Worker 不共享内存,所有数据传递靠结构化克隆(structured clone),不是引用传递,也不能直接调用对方函数。
- 常见错误现象:在 worker 里写
console.log(self)看似正常,但主线程收不到message事件——忘了加worker.onmessage = ...或没在 worker 里写self.onmessage = ... -
postMessage()第二个参数(transfer list)只对ArrayBuffer、MessagePort等可转移对象有效;误传普通数组会触发深拷贝,大数组时明显卡顿 - 不要在 worker 中操作 DOM,也不要用
document、window、alert——这些根本不存在,会报ReferenceError - 简单示例:主线程发数,worker 算平方后返回:
worker.postMessage({id: 1, value: 5})→ worker 内self.onmessage = e => self.postMessage({id: e.data.id, result: e.data.value ** 2})
Worker 报错不显示在控制台?用 onerror 捕获并透传
Worker 内部未捕获的异常默认静默,不会冒泡到主线程,调试时容易以为“没运行”。
- 在 worker 脚本开头加
self.onerror = (e) => self.postMessage({type: 'error', message: e.message, filename: e.filename, lineno: e.lineno}) - 主线程监听:
worker.addEventListener('message', e => { if (e.data.type === 'error') console.error('[Worker]', e.data.message) }) - 注意:
try/catch无法捕获异步错误(如fetch失败、setTimeout内抛错),仍需靠onerror兜底 - Chrome DevTools 的 “Application → Service Workers” 标签页看不到普通 Worker,得去 “Sources → Page → workers” 下找,右键可“Open in Debugger”单步调试
大量 Worker 实例卡死?别滥用,优先考虑 SharedArrayBuffer + Atomics
每个 Worker 是独立 JS 引擎实例,内存和启动开销不小。频繁创建销毁比复用更耗资源。
立即学习“前端免费学习笔记(深入)”;
- 典型误用:为每次 API 请求启一个新 Worker,结果页面卡顿、内存飙升
- 合理做法:预建 2–4 个 Worker 实例组成 pool,用消息 ID 轮询分发任务;或改用
SharedArrayBuffer(需开启跨域策略crossorigin+COOP/COEPheader)配合Atomics.wait()做轻量协同 - 兼容性注意:
SharedArrayBuffer在 Safari 16.4+ 才默认启用,旧版需降级为 MessageChannel + 队列 - 真正需要多线程的场景其实不多:图像像素处理、加密解密、大型 JSON 解析、物理模拟 —— 其他多数情况,用
setTimeout分片或requestIdleCallback更轻量
事情说清了就结束。Web Worker 的核心约束就两条:路径必须可加载、通信必须靠消息。其余问题,基本是绕开了这两条才冒出来的。











