iframe 或者 worker 访问

发布时间:2025-06-24 20:19:13  作者:北方职教升学中心  阅读量:821


1.5Web Worker 和主线程之间的通信方式

workers 和主线程间的数据传递,双方都使用**postMessage()方法发送各自的消息,使用onmessage**事件处理函数来响应消息(消息被包含在message事件的 data 属性中)。iframe 或者 worker 访问。

index.html

<!DOCTYPE html><html lang="en">  <head>    <meta charset="utf-8" />    <meta http-equiv="X-UA-Compatible" content="IE=edge" />    <meta name="viewport" content="width=device-width" />    <title>Web Workers basic example</title>  </head>  <body>    <div class="controls" tabindex="0">      <form>        <div>          <label for="number1">Multiply number 1: </label>          <input type="text" id="number1" value="0" />        </div>        <div>          <label for="number2">Multiply number 2: </label>          <input type="text" id="number2" value="0" />        </div>      </form>      <p class="result">Result: 0</p>    </div>    <script>       const first = document.querySelector('#number1');       const second = document.querySelector('#number2');       const result = document.querySelector('.result');       if (window.Worker) {       // 1.创建一个worker 指定一个js脚本的 URI 来执行 worker 线程       const myWorker = new Worker("worker.js");       [first, second].forEach(input => {         input.onchange = function() {       // 2.主线程给worker发送数据,参数是数组格式           myWorker.postMessage([first.value, second.value]);           console.log('Message posted to worker');         }       })       // 3.主线程监听worker传递过来的信息       //  数据本身在e.data中       myWorker.onmessage = function(e) {         result.textContent = e.data;         console.log('Message received from worker');       }     } else {       console.log('Your browser doesn't support web workers.');     }    </script>  </body></html>

worker.js

// 1.监听主线程发过来的数据onmessage = function(e) {  console.log('Worker: Message received from main script');  const result = e.data[0] * e.data[1];  if (isNaN(result)) {// 2.给主线程发送数据    postMessage('Please write two numbers');} else {    const workerResult = 'Result: ' + result;    console.log('Worker: Posting message back to main script');    postMessage(workerResult);  }}

备注:

  • 在主线程中使用时,onmessagepostMessage()必须挂在worker对象上
  • 而在 worker 中使用时不用这样做。线程可以执行任务而不干扰用户界面。

    • 页面1:

      Shared Workers basic example

      共享Worker示例-页面1

      <div class="controls" tabindex="0">  <form>    <div>      <label for="number1">Multiply number 1: </label>      <input type="text" id="number1" value="0" />    </div>    <div>      <label for="number2">Multiply number 2: </label>      <input type="text" id="number2" value="0" />    </div>  </form>  <p class="result1">Result: 0</p>  <p><a href="index2.html" target="_blank">Go to 示例-页面2</a></p></div><script>   const first = document.querySelector("#number1");   const second = document.querySelector("#number2");   const result1 = document.querySelector(".result1");  if (!!window.SharedWorker) {    // 1.创建一个共享worker    const myWorker = new SharedWorker("worker.js");     // 4.使用端口对象调用postMessage给worker发送信息    first.onchange = function () {    myWorker.port.postMessage([first.value, second.value]);    console.log("Message posted to worker");  };  second.onchange = function () {    myWorker.port.postMessage([first.value, second.value]);    console.log("Message posted to worker");  };    // 2.通过port端口与worker通信    // 3.通过onmessage显式的打开端口连接  myWorker.port.onmessage = function (e) {    result1.textContent = e.data;    console.log("Message received from worker");    console.log(e.lastEventId);  }; }</script>
    • 页面2:创建worker和与worker的过程和页面1是一样的

      Shared Workers basic example

      共享Worker示例-页面2

      <div class="controls" tabindex="0">  <form>    <div>      <label for="number3">Square number: </label>      <input type="text" id="number3" value="0" />    </div>  </form>  <p class="result2">Result: 0</p></div><script>   const squareNumber = document.querySelector("#number3");   const result2 = document.querySelector(".result2");  if (!!window.SharedWorker) {    // 1.创建一个共享worker    const myWorker = new SharedWorker("worker.js");     // 4.使用端口对象调用postMessage给worker发送信息    squareNumber.onchange = function () {    myWorker.port.postMessage([squareNumber.value, squareNumber.value]);    console.log("Message posted to worker");  };    // 2.通过port端口与worker通信    // 3.通过onmessage显式的打开端口连接  myWorker.port.onmessage = function (e) {    result2.textContent = e.data;    console.log("Message received from worker");  }; }</script>
    • worker.js

      // 在父级线程中,设置 onmessage 事件处理函数后
      // 会执行worker的onconnect时间
      onconnect = function (event) {
      // 1.使用事件的 ports 属性来获取端口并存储在变量中
      const port = event.ports[0];
      // 2.为端口添加一个 onmessage 处理函数用来做运算并回传结果给主线程
      port.onmessage = function (e) {
      const workerResult = Result: ${e.data[0] * e.data[1]};
      port.postMessage(workerResult);
      };
      };

    3.在Vue项目中使用 Web Worker

    在vue项目里面不能直接使用**Web Worker,要使用Web Worker有两种方式,一种是使用worker-loader**,一种是使用vue-worker,下面对这两种方法详细介绍。输入的数字会发送给一个专用 worker,由专用 worker 作乘法后,再返回给页面进行展示。Web Worker**为 Web 内容在后台线程中运行脚本提供了一种简单的方法。此外,他们可以使用XMLHttpRequest执行 I/O (尽管responseXML和channel属性总是为空)。

    1.什么是Web Worker

    **Web Worker?**是2008年h5提供的新功能,每一个新功能都是为了解决原有技术的的痛点,那么这个痛点是什么呢?

    1.1 JavaScript的单线程

    JavaScript 为什么要设计成单线程?

    • 这与js的工作内容有关:js只是用来去做一些用户交互,并呈现效果内容。原因是,在 worker 内部,worker 是有效的全局作用域,相当于js环境中的window。
    2.1.2 主线程与worker之间的通信
    • 主线程向worker发送信息

      myWorker.postMessage([first.value, second.value]);

    • 主线程监听worker信息

      myWorker.onmessage = (e) => {
      console.log(e.data);
      };

    • worker监听主线程信息/worker向主线程发送信息

      onmessage = function(e) {
      postMessage(e.data);
      }

    2.1.3 终止worker
    myWorker.terminate();

    worker 线程会被立即终止。

    Web Worker新技术价值,简而言之:提升前端代码运算执行效率

    1.4Web Worker的限制

    • Web Worker,worker 运行在另一个全局上下文中, 有它自己的执行上下文
    • 不能使用window对象的默认方法和属性,不能直接操作 DOM节点。
    • 如果js是多线程,线程一将dom元素的背景色改成红色,线程二将dom元素的背景色改为绿色,那么,到底上红色还是绿色呢?

    但是随着前端的高速发展,前端承担着越来越多的功能,有时需要执行一些复杂的计算任务,但是JavaScript的单线程一旦执行某个耗时的任务,后面的任务都会阻塞,如果在前端能够做多线程的操作,那不就解决这个问题啦,于是,于是Web Worker就应运而生了。

2.2 共享Worker

一个共享 worker可以被多个脚本使用——即使这些脚本正在被不同的 window、

2.1.4 在worker中引入外部脚本

Worker 线程能够访问一个全局函数**importScripts()**来引入脚本,该函数接受 0 个或者多个 URI 作为参数来引入资源

importScripts(); /* 什么都不引入 */importScripts("foo.js"); /* 只引入 "foo.js" */importScripts("foo.js", "bar.js"); /* 引入两个脚本 */importScripts("//example.com/hello.js"); /* 你可以从其他来源导入脚本 */

2.2 独享worker应用案例

将你输入的 2 个数字作乘法。

示例:

在这个示例中有 2 个 HTML 页面,每个页面所包含一个 JavaScript 代码,这两个脚本使用同一个 worker 来完成实际需要的运算。耗时的js运算,这样的话,主线程后续的代码执行就不会阻塞,当辅助线程计算出复杂耗时运算结果后,再与主线程通信,将计算出的结果告知主线程。

3.2 vue-worker

参考:

使用 Web Workers - Web API 接口参考 | MDN

Web Worker 使用教程 - 阮一峰的网络日志

性能优化之使用vue-worker插件(基于Web Worker)开启多线程运算提高效率 - 掘金

Web Worker入门及在 Vue 中如何使用 - 掘金

https://www.npmjs.com/package/vue-worker?activeTab=readme

2. Web Worker 原生用法

2.1 独享Worker

一个专用 worker 仅能被生成它的脚本所使用

2.1.1 创建一个专用worker
const myWorker = new Worker("worker.js");
  • 使用构造器创建worker对象,参数是一个JavaScript 文件——这个文件包含将在 worker 线程中运行的代码。

    1.2 Web Worker的概念

    **????????Web Worker可以创建另外的线程去做一些操作(比如执行一些耗时的操作),这个操作不影响js主线程(比如UI渲染)的执行 。

    3.1 worder-loader

    使用Webpack中的worker-loader插件去解析Web worker,并且在vue.config.js中去做相应配置。一旦创建,一个 worker 可以将消息发送到创建它的 JavaScript 代码,通过将消息发布到该代码指定的事件处理程序(反之亦然)…

    使用 Web Workers - Web API 接口参考 | MDN

    1.3Web Worker的价值

    **????????Web Worker**创建的一些辅助线程,分别去帮主线程分担一些复杂的、这个过程中数据并不是被共享而是被复制。