HTML5笔记——web worker

什么是web worker

MDN:用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。

Web Worker 可以使脚本运行在新的线程中,它们独立于主线程,可以进行大量的计算活动,而不会影响主线程的 UI 渲染。当计算结束之后,它们可以把结果发送给主线程,从而形成了高效、良好的用户体验。Web Worker 是一个统称,具体可以细分为普通的 Worker、SharedWorker 和 ServiceWorker 等。

在 worker 线程中可以运行任何代码,不过有一些例外情况。因为 workers 运行在另一个全局上下文中,所以

  • 不能直接操作 DOM 节点
  • 无法访问 window 对象
  • 无法访问 document 对象
  • 无法访问 parent 对象

消息机制

workers 和主线程间的数据传递

  • postMessage():发送各自的消息
  • onmessage:响应消息(event.data

这个过程中数据并不是被共享而是被复制。

普通 Worker

1.创建 Worker 通过 new 的方式来生成一个实例,参数为 url 地址,该地址必须和其创建者是同源的。

   const worker = new Worker('./worker.js'); // 参数是url,这个url必须与创建者同源 

2.Worker 的方法

  • onmessage 主线程中可以在 Worker 上添加 onmessage 方法,用于监听 Worker 的信息。

    示例:

     const worker = new Worker('./worker.js');
     worker.onmessage = function (messageEvent) {
       console.log(messageEvent)
     } 
  • onmessageerror 主线程中可以在 Worker 上添加 onmessageerror 方法,用于监听 Worker 的错误信息。

    示例:

     const worker = new Worker('./worker.js');
     worker.onmessageerror = function (messageEvent) {
       console.log(messageEvent)
     } 
  • postMessage() 主线程通过此方法给 Worker 发送消息,发送参数的格式不限(可以是数组、对象、字符串等),可以根据自己的业务选择。

    示例:

const worker = new Worker('./worker.js');
worker.postMessage({ type: 'start', payload: { count: 666 } }); // 发送信息给worker
  • terminate() 主线程通过此方法终止 Worker 的运行。

    示例:

     const worker = new Worker('./worker.js');
     worker.terminate();

3.通信

Worker 的作用域跟主线程中的 Window 是相互独立的,并且 Worker 中是获取不到 DOM 元素的。所以在 Worker 中你无法使用 Window 变量。取而代之的是可以用 self 来表示全局对象。self 上有哪些方法和属性,感兴趣的小伙伴可以自行输出查看。比较常用的方法是 onmessage、postMessage,主要用来跟主线程进行通信。

示例:

   // 监听事件,主线程可以通过 postMessage 发送信息过来
   self.onmessage = (messageEvent) => {
     const { type, payload } = messageEvent.data;
     switch (type) {
       case 'start':
         // 通过 type 去区分不同的业务逻辑,payload 是传过来的数据
         const result = 0;
         // ....,通过一系列处理之后,把最终的结果发送给主线程
         this.postMessage(result);
         break;
     }
   };

这里我们从 messageEvent.data 中获取从主线程传递过来的数据。为了业务的扩展性,这边是以 type 去区分不同的业务,payload 承载数据源,通过处理之后把结果发给主线程。主线程的 onmessage 回调函数中就能收到这个结果了。

SharedWorker

SharedWorker 是一种特定的 Worker。从它的命名就能知道,它是一种共享数据的 Worker。它可以同时被多个浏览器环境访问。这些浏览器环境可以是多个 window, iframes 或者甚至是多个 Worker,只要这些 Workers 处于同一主域。为跨浏览器 tab 共享数据提供了一种解决方案。

生成一个Shareworker

var myWorker = new SharedWorker("worker.js");

与专用 Worker 一个最大的区别是:共享 worker 通信必须通过端口对象(一个确切的打开的端口),在专用 worker 中这一部分是隐式进行的。

在传递消息之前,端口连接必须被显式的打开,打开方式是使用 onmessage 事件处理函数或者 start() 方法。如果消息事件被 addEventListener() 方法使用,则选择 start() 打开端口:

myWorker.port.start(); // 父级线程中的调用
port.start(); // worker线程中的调用, 假设port变量代表一个端口

消息的接收和发送

postMessage() 方法必须被端口对象调用。

首先,在主线程中,向 worker 发送消息:

// main.js
myWorker.port.postMessage();

在 worker 中,接受消息的流程会比较复杂:

  • 当一个端口连接被创建时(例如:在父级线程中,设置 onmessage 事件处理函数,或者显式调用 start() 方法时),使用 onconnect 事件来执行函数
  • 获取端口(event.ports[0]
  • 为端口添加一个消息处理函数 onmessage(隐式的打开了与主线程的端口连接)
// worker.js
onconnect = function (e) {
  var port = e.ports[0];

  port.onmessage = function (e) {
    var workerResult = "Result: " + e.data[0] * e.data[1];
    port.postMessage(workerResult);
  };
};

最后,在主线程中接收消息:

// main.js
myWorker.port.onmessage = function (e) {
  result2.textContent = e.data;
  console.log("Message received from worker");
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值