用于优化js的耗时运算,因为js 是单线程的,有些数据量大或很麻烦的数据运算的时候可能会阻塞主线程,导致页面卡顿,因此 webWorker的诞生就是为了解决这个问题,它可以将耗时的数据运算放到后台运行,和主线程进行通信,不占用主线程,从而解决了阻塞。
优势总结:
- 解放主线程:可以将webscoket连接这种持久连接通信放在 webworker中处理,避免阻塞主线程。这样耗时运算在后台运行了,页面不会被阻塞导致卡死,其他地方点了没反应啥的,但是并没有将运算时间缩短。
- 独立在后台运行不受主线程影响,比如即使用户关闭了网页,仍然可以保持 webscoket 连接实现离线消息推送等功能。
- 分布式计算:通过将耗时运算或者持久连接ws放在 web Worker 或者 service Worker 中 可以实现分布式计算,将计算任务分散到多个浏览器实例中进行处理,提高计算效率。
tip:如果页面卡顿不知道什么问题,可以用最小单元测试的方法来排除:
比如怀疑很耗时的数据运算方法导致的,可以将他们先替换成计算好的数据直接返回,看看是否还有卡顿现象,如果不卡了,说明就是运算导致可以将运算提出来放到 webWorker 中处理。
使用 webWorker 注意事项:
- webWorker中没有 DOM(document等),BOM(window等),纯JS语法都是可以用的,所有有关涉及到Dom操作的内容不能放在worker中,可以把处理好的数据传给主线程中处理。
- webWorker 不能用本地文件,只能用网络上的同源文件,因此可以放到静态资源下,或者部署到服务器的指定的静态资源里
- 不是所有东西都可以从主进程传递过去的,只能传递数据,不能传递函数,DOM节点,还有一些对象里的特殊设置(freeze,getter,setter 等) ,所以Vue的响应式对象是不能传递的
- 使用完成后没必要用了的话需要关闭他,为了节省系统资源 ,必须关闭他。
- 模块的引入问题:
直接 new Worker("http://www.xxx.com/A.js") 创建的worker文件是不直接支持 ES Module模块化的,或者需要支持 80 之前版本的 Chrome的话(因为从 Chrome 80+ 才开始支持 ES Module 模块化),想要在 A.js 中引入第三方文件需要用 :
importScripts('http://www.xxx.com/XXX.js')//不限制必须同源,都可以引入
const a = 1+1;
self.postMessage(a)
这种引入方式用于:不支持模块化的运行环境、引入非模块化的包(纯js包,iife 那种)。
但是这种引入方式有缺点:引入的代码会全部执行,无法按需引入。
在支持ES Module的浏览器这样写:这样就能使用import 、export了。用于引入esm的包。
const worker1 = new Worker("http://www.xxx.com/A.js",{
type:module
})
要是引入node_modules 中的库的话,可以从node_modules中找到该库的js包 复制到public下去引入。
基本使用方法:
const tableDataWorker = new Worker("/tableDataWorker.js", {
type: "module",
});
tableDataWorker.postMessage("nihao");
tableDataWorker.addEventListener("message", (e) => {
console.log(e, "hookeeeeeeeeeeeee");
});
const a = 12343423;
self.postMessage(a);
self.addEventListener("message", (e) => {
console.log(e, "workereeeeee");
});
相关参考: