行业知识
前端webWorker 的介绍以及应用
文章目录
- webWorker
- 以下是关于 Web Workers 的一些关键概念:
- 控制台查看
- 使用注意事项
- 消息传递
- 创建subworker
- webWorker的具体使用
- 注意事项
- 共享worker(SharedWorker)
- 创建方法:
- 与专用worker的主要区别:
webWorker
JavaScript是单线程的语言,如果在浏览器中需要执行一些大数据量的计算,页面上的其他操作就会因为来不及响应而出现卡顿的情况,因为这时js还在帮你完成上一个指令呢!这对用户体验来说是极其糟糕的。拿BIM数据的轻量化展示来说,在浏览器端展示大体量的模型,需要从约定的标准模型数据格式中先请求回来各种数据,然后解析计算各种顶点、颜色、属性数据等,在这段过程中前端页面就需要等待一段时间。
webWorker 使用场景:Web Worker 在处理一些耗时的计算、大量数据的处理和其他计算密集型任务方面表现出色,可以提高整体的性能和用户体验。但要注意,它们并不适用于所有的场景,特别是涉及到直接操作 DOM 的情况。
以下是关于 Web Workers 的一些关键概念:
- 线程模型: 在传统的浏览器中,JavaScript 是在主线程中运行的,而主线程主要负责处理用户界面和与用户交互的任务。使用 Web Workers 可以创建额外的线程,这些线程在后台运行,独立于主线程。
- 独立的全局上下文: 每个 Web Worker 都有自己独立的全局上下文,与主线程中的全局上下文是分离的。这意味着在 Web Worker 中定义的变量和函数不会影响主线程中的环境,反之亦然。
- 通信: 主线程和 Web Worker 之间通过消息进行通信。可以使用 postMessage 方法发送消息,并在两者之间建立双向通信。消息传递是通过拷贝而不是共享对象来完成的,确保数据的安全性。
- 不能访问 DOM: Web Workers 不能直接访问 DOM,这意味着不能直接操作页面上的元素。它们主要用于处理计算密集型的任务,而不是用户界面的交互。
- 网络请求: Web Workers 可以执行异步操作,包括发起网络请求。它们可以执行一些与网络相关的任务而不会阻塞主线程。
- 生命周期: Web Workers 有自己的生命周期,可以通过事件监听器(如 onmessage 和 onerror)来捕获相关事件。当不再需要一个 Web Worker 时,可以通过调用 terminate 方法来终止它。
- 限制: 由于 Web Workers 在独立的线程中运行,因此它们不能直接访问主线程的变量和函数。通信是通过消息传递实现的,这也导致了一些数据的复制开销。
控制台查看
使用注意事项
-
同源限制:worker脚本与主进程的脚本必须遵守同源限制。他们所在的路径协议、域名、端口号三者需要相同
-
接口限制:window作用域下的部分方法不可使用,如DOM对象、window.alert和window.confirm等方法。可使用参考 Supported Web APIs
-
文件限制:无法加载本地js文件,必须使用线上。
-
记得关闭:worker会占用一定的系统资源,在相关的功能执行完之后,一定要记得关闭worker。
父进程中使用:worker.terminate(); 关闭;
在worker进程内部关闭 self.close();
消息传递
主进程和worker之间通过发送消息的机制进行通信。对于主进程和worker自身:
- 都使用postMessage发送消息
- 都使用onmessage接收消息
- 都使用onerror监听错误事件
在主进程中onmessage、onerror和postMessage 必须挂在worker对象上。在worker中使用时
self.onmessage \self.postMessage\ self.onerror就行,或者不写self,因为在worker内部,self指向worker自己
创建subworker
在一个worker中创建多个子worker分别处理不同的内容
注意:子worker与父worker同样需要遵守同源限制。
webWorker的具体使用
页面
import BackButton from '/@/components/BackButton/index.vue';import { onMounted, reactive, watch } from 'vue';const props = defineProps({ value: { type: String, default: '', },});onMounted(() => {});var worker = new Worker('worker.js');// 向 Worker 发送消息worker.postMessage(100); // 传递数据,例如计算斐波那契数列的第 30 项// 监听从 Worker 返回的消息worker.onmessage = function (event) { var result = event.data; console.log('Worker 返回的结果1:', result); // 关闭 Worker worker.terminate();};// 监听 Worker 的错误信息worker.onerror = function (error) { console.error('Worker 发生错误:', error);};/** * 开多个线程 */var worker2 = new Worker('worker2.js');worker2.postMessage(10); // 传递数据,例如计算斐波那契数列的第 30 项// 监听从 Worker 返回的消息worker2.onmessage = function (event) { var result = event.data; console.log('Worker 返回的结果2:', result); // 关闭 Worker worker.terminate();};// 监听 Worker 的错误信息worker2.onerror = function (error) { console.error('Worker 发生错误:', error);};
test webworker
worker.js
self.onmessage = function (event) { console.log(event); let data = event.data // 计算处理大数据量的逻辑 let result = fn(data) // 将结果发送回主线程 self.postMessage(result)}// 大数据量的逻辑function fn(n) { let result = 0 for (let i = 0; i result += i } return result} var port = e.ports[0]; port.onmessage = function(e) { var workerResult = 'Result: ' + (e.data[0] * e.data[1]); port.postMessage(workerResult); } port.start();} // xxx console.log('Message received from worker');});myWorker.port.start(); console.log('接收到index页面的数据:' + e.data); let one = document.querySelector('#one') one.innerHTML = e.data[1] } //发送数据给sharedworker document.querySelector("#add").onclick = function () { let count = Number(document.getElementById('one').innerHTML) count++ worker.port.postMessage(['one', count]); document.querySelector('#one').innerHTML = count }; id: 'one' }) worker.port.onmessage = function (e) { console.log('接收到index页面的数据:' + e.data); let one = document.querySelector('#two') one.innerHTML = e.data[1] } var port = e.ports[0]; port.addEventListener('message', function (e) { console.log(e); if (e.data.id) { var index = list_id.indexOf(e.data.id); console.log(index); if (index === -1) { list.push(port); list_id.push(e.data.id); } else { //关闭上个链接 list[index].close(); list[index] = port; }; } else { if (e.data[0] == 'first') { port.postMessage(e.data) } else { send(e.data[1], e.data[0]); } }; }); port.start();}var send = function (data, id) { var index = list_id.indexOf(id); console.log(index); if (index !== -1) { list[index].postMessage([id, data]); };};
-
上一篇:服务器灰尘清理怎么收费?
下一篇:抖音视频下载方法指南