一、JS 单线程困境
- JS 是单线程:所有任务在主线程排队,无法并行。
- 阻塞问题:耗时计算会阻塞 UI 渲染、交互,导致页面卡顿、掉帧。
- 设计原因:保证 DOM 操作原子性,避免多线程竞态冲突。
二、Web Worker 是什么
- 允许 JS 创建独立后台线程,不阻塞主线程。
- 专门处理耗时计算、大数据处理。
- 主线程负责 UI,Worker 负责计算,真正并行。
三、核心能力与限制
✅ 能做
- 复杂计算、循环、数据处理
fetch/XHR网络请求setTimeout/setIntervalPromise、IndexedDB、WebSocket
❌ 不能做(禁区)
- 不能操作 DOM(无 document、window)
- 不能用
localStorage/sessionStorage - 不能用
alert/confirm
四、通信机制
- 主线程 ↔ Worker 线程 通过
postMessage通信。 - 传值不传址 :使用结构化克隆算法,深拷贝传递,不共享内存,线程安全。
- 接收数据用
onmessage或addEventListener('message')。
五、创建与使用
js
// 主线程
const worker = new Worker('./task.js', { type: 'module' })
worker.postMessage(data)
worker.onmessage = (e) => { /* 接收结果 */ }
js
// worker.js
self.onmessage = (e) => {
// 处理耗时任务
self.postMessage(result)
}
六、关闭线程(生命周期)
-
主线程强制关闭
js
jsworker.terminate()立即停止,可能丢失数据。
-
Worker 内部优雅关闭
js
jsself.close()完成当前任务后关闭,更安全。
七、错误处理
onerror:监听 Worker 内部运行错误。onmessageerror:监听数据序列化 / 解析失败。
八、模块化与依赖
- 传统方式 :
importScripts('./a.js', './b.js') - ES 模块 :
new Worker('task.js', { type: 'module' }),支持import/export。
九、SharedWorker(共享线程)
- 同源多标签页共享同一个线程。
- 用于:跨页通信、状态同步、共享计算。
- 基于
port通信,需监听connect事件。 - 典型场景:多标签页同步计数、音乐播放状态、在线文档协同。
十、结构化克隆算法
- 比 JSON 更强:支持
Date、RegExp、Blob、ArrayBuffer、循环引用。 - 不能克隆:Function、Error、DOM 节点。
- Transferable:二进制数据可转移所有权,零拷贝,性能极高。
十一、最佳使用场景
- 大量数据计算、解析、排序、加密解密
- 图像处理、Canvas 数据计算
- 长循环、大数据遍历
- 多页面状态同步(SharedWorker)
十二、总结
Web Worker = 浏览器给 JS 开的后台计算线程,不卡 UI、不碰 DOM、靠消息通信、传值不传址。