ToB企服应用市场:ToB评测及商务社交产业平台

标题: 前端webWorker 的先容以及应用 [打印本页]

作者: 宁睿    时间: 2024-6-14 18:05
标题: 前端webWorker 的先容以及应用
webWorker

JavaScript是单线程的语言,如果在欣赏器中必要执行一些大数据量的计算,页面上的其他操作就会因为来不及响应而出现卡顿的环境,因为这时js还在帮你完成上一个指令呢!这对用户体验来说是极其糟糕的。拿BIM数据的轻量化展示来说,在欣赏器端展示大要量的模子,必要从约定的标准模子数据格式中先哀求回来各种数据,然后剖析计算各种顶点、颜色、属性数据等,在这段过程中前端页面就必要等待一段时间。
webWorker 利用场景:Web Worker 在处理一些耗时的计算、大量数据的处理和其他计算麋集型任务方面体现出色,可以进步团体的性能和用户体验。但要注意,它们并不适用于全部的场景,特殊是涉及到直接操作 DOM 的环境。
以下是关于 Web Workers 的一些关键概念:


控制台检察


利用注意事项


消息通报

主历程和worker之间通过发送消息的机制举行通信。对于主历程和worker自身:

在主历程中onmessage、onerror和postMessage 必须挂在worker对象上。在worker中利用时
self.onmessage \self.postMessage\ self.onerror就行,或者不写self,因为在worker内部,self指向worker自己
创建subworker

在一个worker中创建多个子worker分别处理差别的内容
注意:子worker与父worker同样必要遵守同源限定。

webWorker的具体利用


页面
  1. <script lang="ts" setup>
  2. import BackButton from '/@/components/BackButton/index.vue';
  3. import { onMounted, reactive, watch } from 'vue';
  4. const props = defineProps({
  5.   value: {
  6.     type: String,
  7.     default: '',
  8.   },
  9. });
  10. onMounted(() => {});
  11. var worker = new Worker('worker.js');
  12. // 向 Worker 发送消息
  13. worker.postMessage(100); // 传递数据,例如计算斐波那契数列的第 30 项
  14. // 监听从 Worker 返回的消息
  15. worker.onmessage = function (event) {
  16.   var result = event.data;
  17.   console.log('Worker 返回的结果1:', result);
  18.   // 关闭 Worker
  19.   worker.terminate();
  20. };
  21. // 监听 Worker 的错误信息
  22. worker.onerror = function (error) {
  23.   console.error('Worker 发生错误:', error);
  24. };
  25. /**
  26. * 开多个线程
  27. */
  28. var worker2 = new Worker('worker2.js');
  29. worker2.postMessage(10); // 传递数据,例如计算斐波那契数列的第 30 项
  30. // 监听从 Worker 返回的消息
  31. worker2.onmessage = function (event) {
  32.   var result = event.data;
  33.   console.log('Worker 返回的结果2:', result);
  34.   // 关闭 Worker
  35.   worker.terminate();
  36. };
  37. // 监听 Worker 的错误信息
  38. worker2.onerror = function (error) {
  39.   console.error('Worker 发生错误:', error);
  40. };
  41. </script>
  42. <template>
  43.   <br />
  44.   <div class="m-10">
  45.     <div class="flex-start">
  46.       <BackButton />
  47.     </div>
  48.     <h1>test webworker</h1>
  49.   </div>
  50. </template>
  51. <style lang="less" scoped></style>
复制代码
worker.js
  1. self.onmessage = function (event) {
  2.     console.log(event);
  3.     let data = event.data
  4.     // 计算处理大数据量的逻辑
  5.     let result = fn(data)
  6.     // 将结果发送回主线程
  7.     self.postMessage(result)
  8. }
  9. // 大数据量的逻辑
  10. function fn(n) {
  11.     let result = 0
  12.     for (let i = 0; i <= n; i++) {
  13.         result += i
  14.     }
  15.     return result
  16. }
复制代码
注意事项

注意:worker.js 最好放到public文件夹下,否则打包后可能找不到文件
worker.postMessage(dade),这里如果data内容过多或者布局复杂传不过去(有报错),我暂时想一个方法:JSON.stringify(data)转换成字符串,在worker.js中担当用JSON.parse(event.data),还有如果用.ts报错,那就js,这些是我实际用的时候遇到的题目
下面的图片你细致看其实就是将 [{},{}] 的数据格式转换成二维数组的格式,但是由于这里有几十万条数据,特殊多,处理起来就造成的主线程的卡顿,全部就多开了一个线程;

共享worker(SharedWorker)

上面创建worker的方式在MDN中被归类为专用worker的用法。另一类worker是共享worker,其实际用途与专用worker差别并不大,对于一些公用的方法可以放在共享Worker中供不用的场景利用。SharedWorker可以:

创建方法:

  1. // 在同源的两个页面中都创建SharedWorker,使用同一个脚本
  2. var myWorker = new SharedWorker("xxx.js");
复制代码
与专用worker的主要区别:

在共享worker的利用环境下,主历程和worker的监听和发送消息都要在port端口下举行
  1. myWorker.port.postMessage([first.value, second.value]);
复制代码
共享worker端口启动后时,两个页面的主历程都会向 worker 发送消息。在worker中利用事件监听必要放在onconnect事件中举行
  1. onconnect = function(e) {
  2.   var port = e.ports[0];
  3.   port.onmessage = function(e) {
  4.     var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
  5.     port.postMessage(workerResult);
  6.   }
  7.   port.start();
  8. }
复制代码
如果利用 addEventListener 方式监听 worker消息事件,必要在主历程中利用myWorker.port.start()方法自动启动端口,利用onmessage监听则不用调用启动的方法。
  1. myWorker.port.addEventListener('message', function(e) {
  2.     // xxx
  3.     console.log('Message received from worker');
  4. });
  5. myWorker.port.start();
复制代码
在onconnect中利用port.onmessage和port.postmessage举行监听和发送
主历程中利用 port.postMessage()和 port.onmessage 处理从 worker 返回的消息
eg:

注意开启服务
index.html
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>111</title>
  7. </head>
  8. <body>
  9.     <div><button id="add">add</button></div>
  10.     <h1 id="one">12</h1>
  11.     <!-- <iframe src="index2.html" style="width: 600px;height: 600px; border: 1px solid red;"></iframe> -->
  12. </body>
  13. </html>
  14. <script>
  15.     let worker = new SharedWorker('sharedworker.js')
  16.     worker.port.postMessage(['first', 66])
  17.     worker.port.onmessage = function (e) {
  18.         console.log('接收到index页面的数据:' + e.data);
  19.         let one = document.querySelector('#one')
  20.         one.innerHTML = e.data[1]
  21.     }
  22.     //发送数据给sharedworker
  23.     document.querySelector("#add").onclick = function () {
  24.         let count = Number(document.getElementById('one').innerHTML)
  25.         count++
  26.         worker.port.postMessage(['one', count]);
  27.         document.querySelector('#one').innerHTML = count
  28.     };
  29. </script>
复制代码
index2.html
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>222</title>
  7. </head>
  8. <body>
  9.     <h1 id="two">two</h1>
  10. </body>
  11. </html>
  12. <script>
  13.     console.log(window.SharedWorker);
  14.     let worker = new SharedWorker('sharedworker.js')
  15.     worker.port.postMessage({ id: 'one' })
  16.     worker.port.onmessage = function (e) {
  17.         console.log('接收到index页面的数据:' + e.data);
  18.         let one = document.querySelector('#two')
  19.         one.innerHTML = e.data[1]
  20.     }
  21. </script>
复制代码
sharedworker.js
  1. var list = [];
  2. var list_id = [];
  3. onconnect = function (e) {
  4.     var port = e.ports[0];
  5.     port.addEventListener('message', function (e) {
  6.         console.log(e);
  7.         if (e.data.id) {
  8.             var index = list_id.indexOf(e.data.id);
  9.             console.log(index);
  10.             if (index === -1) {
  11.                 list.push(port);
  12.                 list_id.push(e.data.id);
  13.             } else {
  14.                 //关闭上个链接
  15.                 list[index].close();
  16.                 list[index] = port;
  17.             };
  18.         }
  19.         else {
  20.             if (e.data[0] == 'first') {
  21.                 port.postMessage(e.data)
  22.             } else {
  23.                 send(e.data[1], e.data[0]);
  24.             }
  25.         };
  26.     });
  27.     port.start();
  28. }
  29. var send = function (data, id) {
  30.     var index = list_id.indexOf(id);
  31.     console.log(index);
  32.     if (index !== -1) {
  33.         list[index].postMessage([id, data]);
  34.     };
  35. };
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4