vite中使用web worker
1.web worker介绍
JavaScript是单线程模型,所有任务只能在一个线程上完成,前面的事情没有完毕,后面的事情要等待前面的事情处理完毕后才能执行。但随着电脑计算能力的增强,尤其是多核CPU的出现,单线程已无法充分发挥计算机的计算能力。
web worker可为 JavaScript创造多线程环境,允许主线程创建worker线程,可将一些计算密集型或高延迟的任务分配给worker。worker 线程在后台运行,与主线程互不干扰。等到 worker 线程完成计算任务,再把结果返回给主线程。如此,可有效提高应用性能。
2.原生环境使用web worker
**原生环境使用`worker`示例:**
下面代码功能,主线程发送两个数字给worker,worker求两数字之和,再将结果发送回主线程
`./main.js` `(main thread)`
// 兼容性判断
if (window.Worker) {
// 1.创建一个worker
const myWorker = new Worker('worker.js');
// 2.worker消息监听
myWorker.onmessage = e => {
const data = e.data;
console.log(`Message received from worker, sum: ${data.sum}`);
};
// 3.worker异常监听
myWorker.onerror = e => {
console.error(e);
};
// 4.向worker线程发送数据,注意,只能传递一个参数,如有多个参数,可以包装成Object
myWorker.postMessage({ a: 1, b: 2 });
// 5.当离开页面的时候,或者需要结束worker时(比如任务完成时),
// 可以结束Worker线程,不必占用资源
// myworker.terminate();
} else {
// 不支持web worker
console.log("Your browser doesn't support web workers.");
}
`./worker.js` `(worker thread)`
// 1.监听主线程消息
self.onmessage = e => {
// 2.接收来自主线程发送过来的数据
const data = e.data;
console.log(`Message received from main thread, a: ${data.a}, b: ${data.b}`);
const sum = data.a + data.b;
// 3.将结果发送给主线程
self.postMessage({ sum });
};
// 4.在worke 线程中也可以监听错误信息
self.onerror = e => {
console.log(e);
};
// 5.worker线程也可以调用close结束worker线程
// self.close();
一些API说明:
-
主线程可调用原生
APIWorker()函数,新建一个workerWorker()构造函数的参数是一个脚本文件,该文件就是worker线程所要执行的任务。var worker = new Worker('work.js'); -
然后,主线程可调用
worker.postMessage()方法,向worker发消息worker.postMessage('Hello World'); -
接着,主线程通过
worker.onmessage定义监听函数,接收worker发回来的消息worker.onmessage = (e) => { console.log('Received message: ' + e.data); } -
最后,
worker完成任务以后,主线程就可以把它关掉worker.terminate();
web worker注意点:
-
同源限制
worker脚本文件必须与主线程文件同源。 -
API限制worker线程的全局对象与主线程不一样,无法读取网页的DOM对象,也无法使用document、window、parent这些对象。但是可以使用navigator对象和location对象。也可以使用XMLHttpRequest对象发出AJAX请求。 -
通信
worker线程和主线程不在同一个上下文环境,不能共用变量,如果要交互信息,必须通过postMessage完成。
3.vite中使用web worker
vite也支持web worker,不过其中存在一些陷阱,官方提供了两种使用web worker的方式,官方文档传送门:
-
带有查询后缀的导入
import Worker from './worker.js?worker' const worker = new Worker()此方式在
vite2.x版本下,可在测试环境和正式环境正常使用(亲测) -
通过构造器导入(官方推荐方式)
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module', })此方式在
vite2.x版本下,只能在测试环境正常工作,无法用于生产环境(亲测)
在vite中使用的完整示例,依然是实现求和功能:
main.js (也可以是.vue文件中的任意主线程脚本)
import myWorker from './myWorker?worker&inline';
let worker = null;
if (window.Worker) {
worker = new myWorker();
worker.onmessage = e => {
const data = e.data;
console.log(data.sum);
};
worker.onerror = e => console.error(e);
}
if (worker) {
worker.postMessage({ a: 1, b: 2 });
}
myWorker.js(需要处于src目录下,如果处于public目录将无法使用,亲测)
self.onmessage = e => {
const data = e.data;
const sum = data.a + data.b;
self.postMessage({ sum });
};
self.onerror = e => console.log(e);