众所周知,JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。
针对我们业务上来讲,一旦我们执行了过多的长任务,执行过程很容易就被阻塞,出现页面假死的现象。虽然我们可以将任务放在任务队列中,通过异步的方式执行,但这并不能改变JS的本质。
所以为了改变这种现状,whatwg推出了Web Workers。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Web Worker 有以下几个使用注意点:
1.同源限制:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
2.DOM 限制:Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,3.也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
4.通信联系:Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
5.脚本限制:Worker 线程不能执行alert()方法和confirm()方法,但可以XMLHttpRequest 对象发出 AJAX 请求。
6.文件限制:Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络
开始实践
❀安装worker-loader
npm install worker-loader
❀配置vite
需在这个文件中声明 否则引入是会报错(目前是ts会有这个报错,js目前暂不清楚)
vite.config.ts
chainWebpack: (config: any) => {
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use({
loader: 'worker-loader',
options: {
inline: true,
},
})
.loader('worker-loader')
.end();
},
❀source.d.ts
declare module 'worker-loader';
❀worker.ts
(function () {
self.addEventListener('message', (e: any) => {
// 结构传过来的值,不清楚的打印data
let { data } = e.data;
postMessage({ msg: 'data', data }); // 发送数据
console.log('发送成功');
});
})();
❀main.vue
//页面调用
import Worker from './worker.ts?worker'; //引入
const worker = new Worker(); //注册
worker.postMessage({ a: window.earthViewer.sence }); // 调用传值
worker.onmessage = (e: { data: any }) => {
// 成功之后接受信息
};
这里注意 如果ts当中使用的话需使用上述的引用方式 否则会报错