【web worker】独立于主线程

简介

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 凭证。该值可以是 omitsame-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 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

本次分享结束,感谢大家捧场,共同进步!

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值