web前端性能优化篇(一) Web Worker

[复制链接]
发表于 2025-6-7 17:58:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
概要

记录一下前端中听过,但是一般很少用到的前端技术 -—— Web Worker;
起首要明白为什么使用web worker。由于js 代码的实现采用的是单线程,也就说同一时刻只能做一件事,但是假如出现多个使命同时执行,那么在这段使命执行完成之前,后面的代码是不会执行的,从而导致壅闭,用户的交互会可能会出现无响应状态,影响用户体验。
什么是Web Worker

Html5提供了并规范了Web worker 这一套API。他允许JS在运行的主线程之外运行另一个线程(即Worker线程)。
使用权限


  • 分享给worker运行的脚本文件,不许与主线程的脚本文件同源
  • Worker是无法加载读取本地文件的,它所加载的脚本资源必须来自网络。
  • Worker如今地点的全局情况变量是与主线程不一样的。


  • 无法读取主线程地点网页的DOM对象
  • 无法操纵document 、window 、 parent这些对象。

  • Worker线程同时不能使用alert()和confirm()方法,但是可以使用XMLHttpRequest对象发出哀求,同时也可以使用setTimeout/setInterval()等API。
技术细节

代码:
  1. const worker = new Worker(aURL, options);
复制代码
相干的使用方法:


  • worker.postMessage: 向 worker 的内部作用域发送一个消息,消息可由任何 JavaScript 对象组成
  • worker.terminate: 立刻终止 worker。该方法并不会等待 worker 去完成它剩余的操纵;worker 将会被立刻停止
  • worker.onmessage:当 worker 的父级吸取到来自其 worker 的消息时,会在 Worker 对象上触发 message 事件
  • worker.onerror: 当 worker 出现运行中错误时,它的 onerror 事件处置惩罚函数会被调用。
  1. worker.addEventListener('error', function (e) {
  2.     console.log(e.message) // 可读性良好的错误消息
  3.     console.log(e.filename) // 发生错误的脚本文件名
  4.     console.log(e.lineno) // 发生错误时所在脚本文件的行号
  5. })
复制代码
常见使用方式

  1. const myWorker = new Worker(URL, options);
复制代码
此中URL表示 worker 将执行的脚本的 URL(脚本文件), 即 Web Worker 所要执行的使命。
案例:
  1. // 主线程下创建worker线程
  2. const worker = new Worker('./worker.js')
  3. // 监听接收worker线程发的消息
  4. worker.onmessage = function (e) {
  5.   console.log('主线程收到worker线程消息:', e.data)
  6. }
  7. // 向worker线程发送消息
  8. worker.postMessage('主线程发送hello world')
复制代码
同时的,在worker.js中:
  1. // self 代表子线程自身,即子线程的全局对象
  2. self.addEventListener("message", function (e) {
  3.   // e.data表示主线程发送过来的数据
  4.   self.postMessage("worker线程收到的:" + e.data); // 向主线程发送消息
  5. });
复制代码
  在Web Worker中执行的上下文名称是self。
  在Worker中引入其他运行脚本

当要在Worker中引入项目中的其他脚本时,可以使用importScripts()
  1. // worker.js
  2. importScripts("constants.js");
  3. // self 代表子线程自身,即子线程的全局对象
  4. self.addEventListener("message", function (e) {
  5.   self.postMessage(foo); // 可拿到 `foo`、`getAge()`、`getName`的结果值
  6. });
  7. // constants.js
  8. const foo = "变量";
  9. function getAge() {
  10.   return 25;
  11. }
  12. const getName = () => {
  13.   return "jacky";
  14. };
复制代码
Vue3深度集成方案

1:Composition API实现
  1. // useWebWorker.js
  2. import { ref, onUnmounted } from 'vue';
  3. export default function useWebWorker(workerScript) {
  4.   const worker = ref(null);
  5.   const result = ref(null);
  6.   const error = ref(null);
  7.   const initWorker = () => {
  8.     worker.value = new Worker(new URL(workerScript, import.meta.url));
  9.    
  10.     worker.value.onmessage = (e) => {
  11.       result.value = e.data;
  12.     };
  13.     worker.value.onerror = (err) => {
  14.       error.value = err;
  15.       terminateWorker();
  16.     };
  17.   };
  18.   const terminateWorker = () => {
  19.     worker.value?.terminate();
  20.     worker.value = null;
  21.   };
  22.   onUnmounted(terminateWorker);
  23.   return {
  24.     worker,
  25.     result,
  26.     error,
  27.     initWorker,
  28.     postMessage: (msg) => worker.value?.postMessage(msg)
  29.   };
  30. }
复制代码
2:组件级应用
  1. <script setup>
  2. import { computed } from 'vue';
  3. import useWebWorker from './useWebWorker';
  4. const { result, initWorker, postMessage } = useWebWorker('./heavyTask.worker.js');
  5. const calculate = () => {
  6.   initWorker();
  7.   postMessage({ data: largeData });
  8. };
  9. // 计算属性依赖
  10. const formattedResult = computed(() => result.value?.toFixed(2));
  11. </script>
复制代码
小结

虽然在实际开辟展中用到的情况比较少,但是假如考虑到前端页面性能优化的情况,可以往该技术方向进行思索选型。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表