简介
web worker是html5的一个特别的属性,当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。
js最初设计是运行在浏览器中的,为了防止多个线程同时操作DOM,带来渲染冲突问题,所以js执行器被设计成单线程。但随着前端技术的发展,js能力远不止如此,当我们遇到需要大量计算的场景时(比如图像处理、视频解码等),js线程往往会被长时间阻塞,甚至造成页面卡顿,影响用户体验。Web Worker 的产生就是为了解决单线程带来的这一弊端。
如果我们有大量数据或者辅助业务执行时,就可以把这些交给worker线程去处理,这样就可以减少主线程的一部分复杂运算,以达到减少阻塞的时间,另一方面也提高了页面流畅度,运行效率等。
使用
通过new来创建worker,其中包含两个参数。
const worker = new Worker(path, options);
path:有效的js脚本的地址,必须遵守同源策略。无效的js地址或者违反同源策略,会抛出SECURITY_ERR
类型错误。
options:常数(type =>可选,用以指定 worker 类型,该值可以是 classic
或 module,
如未指定,将使用默认值 classic。
credentials =>可选,用以指定 worker 凭证。该值可以是 omit
, same-origin
,或 include
。如果未指定,或者 type 是 classic
,将使用默认值 omit
(不要求凭证)。name =>可选,在 DedicatedWorkerGlobalScope 的情况下,用来表示 worker 的 scope 的一个 DOMString 值,主要用于调试目的。)
创建demo_worker.js,以下为js中的内容
let timer = null;
let count = 0;
const interval = () => {
timer = setInterval(() => {
count++;
postMessage(count);
const nowTime = new Date();
console.log(
"数值:",
count,
"时间:" +
nowTime.getHours() +
":" +
nowTime.getMinutes() +
":" +
nowTime.getSeconds()
);
}, 1000);
};
onmessage = function (event) {
const { data } = event;
if (data === "start") {
interval();
}
if (data === "stop") {
clearInterval(timer);
this.postMessage("ended");
}
console.log(event.data);
};
在调用文件中检测浏览器中是否支持web worker
if(typeof(Worker)!=="undefined")
{
// 是的! Web worker 支持!
// 一些代码.....
}
else
{
//抱歉! Web Worker 不支持
}
当前所使用的是基于vite+vue项目,所以创建方式有所改变。
首先要引入js文件,切记一定要加后缀标明为worker类型
import Worker from "@/utils/demo_worker.js?worker";
对导入内容进行实例化(注册)
// 创建一个新的Web Worker
this.workerItem = new Worker();
注册了worker实例,我们开始发送消息给Worker启动定时器。
this.workerItem.postMessage("start");
当任务不需要再执行,我们可以利用Web Worker提供的terminate方法终止Web Worker任务。它不会等待 worker 去完成它剩余的操作。
this.workerItem.terminate(); // 整体线程终止操作
完整的实例子如下
<template>
<div>
<button @click="startWorker">Start Worker</button>
<button @click="stopWorker">Stop Worker</button>
</div>
</template>
<script>
import Worker from "@/utils/demo_worker.js?worker";
export default {
name: "WorkerComponent",
data() {
return {
num: 0,
workerItem: "",
timer: "",
};
},
methods: {
startWorker() {
// 检查浏览器是否支持Web Worker
if (typeof Worker !== "undefined") {
// 创建一个新的Web Worker
this.workerItem = new Worker();
this.workerItem.onmessage = function (e) {
console.log(e);
if (e && e.data === "ended") {
this.stopWorker();
}
};
this.workerItem.postMessage("start");
} else {
console.log("Your browser doesn't support Web Workers.");
}
},
stopWorker() {
// this.workerItem.postMessage("stop");
this.workerItem.terminate(); // 整体线程终止操作
},
},
};
</script>
Web Worker的限制
在
Web Worker
内
, worker 运行在另一个全局上下文中, 有它自己的执行上下文- 不能使用 window 对象的默认方法和属性,不能直接操作 DOM 节点。
- Worker 线程不能执行
alert()
方法和confirm()
方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。 - Worker 线程无法读取本地文件,即不能打开本机的文件系统(
file://
),它所加载的脚本,必须来自网络。 - Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
本次分享结束,感谢大家捧场,共同进步!