准备给我的一个 Vite 项目进行重构,其中一个功能(函数)要花费 JS 主线程大量时间 ,会导致主线程画面卡死,无法正常点击,直到该功能(函数)执行完毕而言。这样的用户体验非常差,于是就准备使用 WebWorker 对该功能封装。
WebWorker 限制
(1)同源限制
分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
(2)DOM 限制
Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
(3)通信联系
Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
(4)脚本限制
Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
(5)文件限制
Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。
综合以上限制,我所要重构的功能面临以下问题
- 一些 window 下的函数,或者主线程下全局数据函数,无法共同
- 无法读取本地文件,需要创建网络文件(如 Blob 或 Vite 导入)
- Worker 线程和主线程通信要使用
worker.postMessage与self.addEventListener来发送与监听数据。
所以在考虑使用 Worker 的时候就要考虑这个功能是否值得使用 Worker,能否使用 Worker 实现
Vite 中使用 WebWorker
这里先给出我的最优解,在 Vite 中静态资源处理 ,其中可以导入脚本作为 Worker
main.jsjavascript
import Worker from './test.worker.js?worker'
const worker = new Worker()
这个 worker 就是所要的 Worker 对象,接着就可以对象的 postMessage 与 onmessage 来数据通信,如
main.jsjavascript
worker.onmessage = (e) => {
console.log('main.js', e.data)
}
worker.postMessage('hello from main')