Web Worker 类型
1. 为什么 JavaScript 是单线程的?
JavaScript 诞生之初的主要用途是与用户交互以及操作 DOM。如果允许存在多线程,线程 A 想要改变一个 DOM 节点的属性,线程 B 同时想要删除该节点,会导致复杂的同步问题和锁机制,甚至导致浏览器崩溃。为了保持渲染安全和模型简单,JS 采用了单线程执行的模式。
然而随着应用愈加复杂,主线程容易被大数据的计算任务或复杂操作阻塞,导致页面无法及时响应。为了解决这个问题,Web Worker 提供了将执行卸载到后台计算线程的功能。
2. Worker 类型解析
(1) Web Worker
最常规的使用方式。
- 定位:为主线程创建一个专用的后台独立线程,它隶属于当前页面。当页面关闭时,它也会随之销毁。
- 限制:Worker 线程无法访问
window、document 等 DOM 上下文,也无法访问主线程作用域的变量以及 localStorage。
- 适用场景:执行大数据排序、格式化过滤、加解密复杂计算、图像的离线预处理等阻塞主线程的耗时计算任务。
- 通信:通过
postMessage() 与主线程通信。传递非常大的数据时,为了避免深拷贝带来的性能开销,建议使用转移对象的方式直接移交内存块权限。
(2) Shared Worker
- 定位:可以被多个属于同源的窗口、iframe 甚至是不同标签页共同连接与共享的后台单一线程。
- 通信:通信机制较为复杂,需要通过建立多个独立的消息管道来进行隔离与分发处理。
- 适用场景:适用于需要在多个不同窗口间共享复杂状态的场景,或者将多个窗口连接至远端的同一个 WebSocket 下复用单个长连接。
(3) Service Worker
- 定位:并不主要用于算力卸载。它充当是 Web 应用与网络之间的代理服务器,专门处理网络请求和前端缓存管理控制。
- 特点:具备特殊的生命周期控制流,能够拦截进出的网络请求,并决定响应是从网络还是从离线缓存中拉取。常用于实现具有稳定离线能力的应用页面。