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
- const myWorker = new Worker("worker.js");
复制代码
- 利用构造器创建worker对象,参数是一个 JavaScript 文件——这个文件包罗将在 worker 线程中运行的代码。
2.1.2 主线程与worker之间的通信
- myWorker.postMessage([first.value, second.value]);
复制代码
- myWorker.onmessage = (e) => {
- console.log(e.data);
- };
复制代码
- worker监听主线程信息/worker向主线程发送信息
- onmessage = function(e) {
- postMessage(e.data);
- }
复制代码 2.1.3 停止worker
worker 线程会被立即停止。
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 个数字作乘法。输入的数字会发送给一个专用 worker,由专用 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);
- }
- }
复制代码 备注:
- 在主线程中利用时,onmessage 和 postMessage() 必须挂在 worker 对象上
- 而在 worker 中利用时不消如许做。缘故原由是,在 worker 内部,worker 是有用的全局作用域,相当于js情况中的window。
2.2 共享Worker
一个共享 worker 可以被多个脚本利用——即使这些脚本正在被差别的 window、iframe 大概 worker 访问。
示例:
在这个示例中有 2 个 HTML 页面,每个页面所包罗一个 JavaScript 代码,这两个脚本利用同一个 worker 来完成现实需要的运算。
- <!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>Shared Workers basic example</title>
- </head>
- <body>
- <h1>共享Worker示例-页面1</h1>
- <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>
- </body>
- </html>
复制代码
- 页面2:创建worker和与worker的过程和页面1是一样的
- <!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>Shared Workers basic example</title>
- </head>
- <body>
- <h1>共享Worker示例-页面2</h1>
- <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>
- </body>
- </html>
复制代码
- // 在父级线程中,设置 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,下面临这两种方法具体先容。
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企服之家,中国第一个企服评测及商务社交产业平台。 |