在Vue中利用Web Worker具体教程

打印 上一主题 下一主题

主题 898|帖子 898|积分 2694

1.什么是Web Worker?

        Web Worker 是2008年h5提供的新功能,每一个新功能都是为相识决原有技能的的痛点,那么这个痛点是什么呢?
1.1 JavaScript的单线程

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


  • 这与js的工作内容有关:js只是用来去做一些用户交互,并出现结果内容。
  • 如果js是多线程,线程一将dom元素的配景色改成红色,线程二将dom元素的配景色改为绿色,那么,到底上红色照旧绿色呢?
        但是随着前端的高速发展,前端负担着越来越多的功能,偶然需要执行一些复杂的计算任务,但是JavaScript的单线程一旦执行某个耗时的任务,后面的任务都会阻塞,如果在前端可以或许做多线程的操作,那不就办理这个题目啦,于是,于是Web Worker就应运而生了。
1.2 Web Worker的概念

        Web Worker可以创建别的的线程去做一些操作(比如执行一些耗时的操作),这个操作不影响js主线程(比如UI渲染)的执行 。Web Worker为 Web 内容在配景线程中运行脚本提供了一种简朴的方法。线程可以执行任务而不干扰用户界面。此外,他们可以利用XMLHttpRequest执行 I/O (尽管responseXML和channel属性总是为空)。一旦创建,一个 worker 可以将消息发送到创建它的 JavaScript 代码,通过将消息发布到该代码指定的事件处置惩罚步伐(反之亦然)......
   利用 Web Workers - Web API 接口参考 | MDN
  1.3 Web Worker的价值

        Web Worker创建的一些辅助线程,分别去帮主线程分担一些复杂的、耗时的js运算,如许的话,主线程后续的代码执行就不会阻塞,当辅助线程计算出复杂耗时运算结果后,再与主线程通信,将计算出的结果告知主线程。
Web Worker新技能价值,简而言之:提升前端代码运算执行效率 
1.4 Web Worker的限制



  • Web Worker内, worker 运行在另一个全局上下文中, 有它本身的执行上下文
  • 不能利用 window 对象的默认方法和属性,不能直接操作 DOM 节点。
1.5 Web Worker 和主线程之间的通信方式

        workers 和主线程间的数据传递,双方都利用 postMessage() 方法发送各自的消息,利用 onmessage 事件处置惩罚函数来响应消息(消息被包罗在 message 事件的 data 属性中)。这个过程中数据并不是被共享而是被复制。

2. Web Worker 原生用法

2.1 独享Worker

        一个专用 worker 仅能被生成它的脚本所利用
2.1.1 创建一个专用worker

  1. const myWorker = new Worker("worker.js");
复制代码


  •  利用构造器创建worker对象,参数是一个 JavaScript 文件——这个文件包罗将在 worker 线程中运行的代码。
2.1.2 主线程与worker之间的通信



  • 主线程向worker发送信息
  1. myWorker.postMessage([first.value, second.value]);
复制代码


  • 主线程监听worker信息
  1. myWorker.onmessage = (e) => {
  2.   console.log(e.data);
  3. };
复制代码


  • worker监听主线程信息/worker向主线程发送信息 
  1. onmessage = function(e) {
  2.   postMessage(e.data);
  3. }
复制代码
2.1.3 停止worker

  1. myWorker.terminate();
复制代码
        worker 线程会被立即停止。 
2.1.4 在worker中引入外部脚本

         Worker 线程可以或许访问一个全局函数 importScripts() 来引入脚本,该函数担当 0 个大概多个 URI 作为参数来引入资源
  1. importScripts(); /* 什么都不引入 */
  2. importScripts("foo.js"); /* 只引入 "foo.js" */
  3. importScripts("foo.js", "bar.js"); /* 引入两个脚本 */
  4. importScripts("//example.com/hello.js"); /* 你可以从其他来源导入脚本 */
复制代码
2.2 独享worker应用案例 

        将你输入的 2 个数字作乘法。输入的数字会发送给一个专用 worker,由专用 worker 作乘法后,再返回给页面举行展示。
index.html
  1. <!DOCTYPE html>
  2. <html lang="en">
  3.   <head>
  4.     <meta charset="utf-8" />
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6.     <meta name="viewport" content="width=device-width" />
  7.     <title>Web Workers basic example</title>
  8.   </head>
  9.   <body>
  10.     <div class="controls" tabindex="0">
  11.       <form>
  12.         <div>
  13.           <label for="number1">Multiply number 1: </label>
  14.           <input type="text" id="number1" value="0" />
  15.         </div>
  16.         <div>
  17.           <label for="number2">Multiply number 2: </label>
  18.           <input type="text" id="number2" value="0" />
  19.         </div>
  20.       </form>
  21.       <p class="result">Result: 0</p>
  22.     </div>
  23.     <script>
  24.        const first = document.querySelector('#number1');
  25.        const second = document.querySelector('#number2');
  26.        const result = document.querySelector('.result');
  27.        if (window.Worker) {
  28.        // 1.创建一个worker 指定一个js脚本的 URI 来执行 worker 线程
  29.        const myWorker = new Worker("worker.js");
  30.        [first, second].forEach(input => {
  31.          input.onchange = function() {
  32.        // 2.主线程给worker发送数据,参数是数组格式
  33.            myWorker.postMessage([first.value, second.value]);
  34.            console.log('Message posted to worker');
  35.          }
  36.        })
  37.        // 3.主线程监听worker传递过来的信息
  38.        //  数据本身在e.data中
  39.        myWorker.onmessage = function(e) {
  40.          result.textContent = e.data;
  41.          console.log('Message received from worker');
  42.        }
  43.      } else {
  44.        console.log('Your browser doesn\'t support web workers.');
  45.      }
  46.     </script>
  47.   </body>
  48. </html>
复制代码
worker.js
  1. // 1.监听主线程发过来的数据
  2. onmessage = function(e) {
  3.   console.log('Worker: Message received from main script');
  4.   const result = e.data[0] * e.data[1];
  5.   if (isNaN(result)) {
  6. // 2.给主线程发送数据
  7.     postMessage('Please write two numbers');
  8.   } else {
  9.     const workerResult = 'Result: ' + result;
  10.     console.log('Worker: Posting message back to main script');
  11.     postMessage(workerResult);
  12.   }
  13. }
复制代码
   备注: 
  

  • 在主线程中利用时,onmessage 和 postMessage() 必须挂在 worker 对象上
  • 而在 worker 中利用时不消如许做。缘故原由是,在 worker 内部,worker 是有用的全局作用域,相当于js情况中的window。
  2.2 共享Worker

一个共享 worker 可以被多个脚本利用——即使这些脚本正在被差别的 window、iframe 大概 worker 访问。
示例:
        在这个示例中有 2 个 HTML 页面,每个页面所包罗一个 JavaScript 代码,这两个脚本利用同一个 worker 来完成现实需要的运算。


  • 页面1:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3.   <head>
  4.     <meta charset="utf-8" />
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6.     <meta name="viewport" content="width=device-width" />
  7.     <title>Shared Workers basic example</title>
  8.   </head>
  9.   <body>
  10.     <h1>共享Worker示例-页面1</h1>
  11.     <div class="controls" tabindex="0">
  12.       <form>
  13.         <div>
  14.           <label for="number1">Multiply number 1: </label>
  15.           <input type="text" id="number1" value="0" />
  16.         </div>
  17.         <div>
  18.           <label for="number2">Multiply number 2: </label>
  19.           <input type="text" id="number2" value="0" />
  20.         </div>
  21.       </form>
  22.       <p class="result1">Result: 0</p>
  23.       <p><a href="index2.html" target="_blank">Go to 示例-页面2</a></p>
  24.     </div>
  25.     <script>
  26.        const first = document.querySelector("#number1");
  27.        const second = document.querySelector("#number2");
  28.        const result1 = document.querySelector(".result1");
  29.       if (!!window.SharedWorker) {
  30.         // 1.创建一个共享worker
  31.         const myWorker = new SharedWorker("worker.js");
  32.         // 4.使用端口对象调用postMessage给worker发送信息
  33.         first.onchange = function () {
  34.         myWorker.port.postMessage([first.value, second.value]);
  35.         console.log("Message posted to worker");
  36.       };
  37.       second.onchange = function () {
  38.         myWorker.port.postMessage([first.value, second.value]);
  39.         console.log("Message posted to worker");
  40.       };
  41.         // 2.通过port端口与worker通信
  42.         // 3.通过onmessage显式的打开端口连接
  43.       myWorker.port.onmessage = function (e) {
  44.         result1.textContent = e.data;
  45.         console.log("Message received from worker");
  46.         console.log(e.lastEventId);
  47.       };
  48.      }
  49.     </script>
  50.   </body>
  51. </html>
复制代码


  • 页面2:创建worker和与worker的过程和页面1是一样的
  1. <!DOCTYPE html>
  2. <html lang="en">
  3.   <head>
  4.     <meta charset="utf-8" />
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6.     <meta name="viewport" content="width=device-width" />
  7.     <title>Shared Workers basic example</title>
  8.   </head>
  9.   <body>
  10.     <h1>共享Worker示例-页面2</h1>
  11.     <div class="controls" tabindex="0">
  12.       <form>
  13.         <div>
  14.           <label for="number3">Square number: </label>
  15.           <input type="text" id="number3" value="0" />
  16.         </div>
  17.       </form>
  18.       <p class="result2">Result: 0</p>
  19.     </div>
  20.     <script>
  21.        const squareNumber = document.querySelector("#number3");
  22.        const result2 = document.querySelector(".result2");
  23.       if (!!window.SharedWorker) {
  24.         // 1.创建一个共享worker
  25.         const myWorker = new SharedWorker("worker.js");
  26.         // 4.使用端口对象调用postMessage给worker发送信息
  27.         squareNumber.onchange = function () {
  28.         myWorker.port.postMessage([squareNumber.value, squareNumber.value]);
  29.         console.log("Message posted to worker");
  30.       };
  31.         // 2.通过port端口与worker通信
  32.         // 3.通过onmessage显式的打开端口连接
  33.       myWorker.port.onmessage = function (e) {
  34.         result2.textContent = e.data;
  35.         console.log("Message received from worker");
  36.       };
  37.      }
  38.     </script>
  39.   </body>
  40. </html>
复制代码


  • worker.js 
  1. // 在父级线程中,设置 onmessage 事件处理函数后
  2. // 会执行worker的onconnect时间
  3. onconnect = function (event) {
  4.   // 1.使用事件的 ports 属性来获取端口并存储在变量中
  5.   const port = event.ports[0];
  6.   // 2.为端口添加一个 onmessage 处理函数用来做运算并回传结果给主线程
  7.   port.onmessage = function (e) {
  8.     const workerResult = `Result: ${e.data[0] * e.data[1]}`;
  9.     port.postMessage(workerResult);
  10.   };
  11. };
复制代码
3.在Vue项目中利用 Web Worker

        在vue项目里面不能直接利用Web Worker,要利用Web Worker有两种方式,一种是利用worker-loader,一种是利用vue-worker,下面临这两种方法具体先容。
3.1 worder-loader

利用Webpack中的worker-loader插件去解析Web worker,并且在vue.config.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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

络腮胡菲菲

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表