LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

不會webworker,你做什么前端性能優化?

admin
2025年1月6日 21:54 本文熱度 339

作者:落課

https://juejin.cn/post/7433719237455937546


前言

本來這篇文章是打算寫我之前那個迭代首屏優化的,但是我做的那些優化,前幾天上了生產,效果并不如意,因為生產環境不能隨便動,我只能在灰度環境上測試,但是灰度測試后確實是比之前好的。那篇文章我也寫了大半了,過幾天發出來大家指點一下。然后我最近看了評論想著使用webworker去優化一下我那坨列表,然后我之前也沒用過,最近也研究了一下,所以這篇文章就給大家分享一下webworker怎么用。其實挺簡單的,但是遇到了一些坑!希望大家使用的時候能注意一下。

什么是web worker?

mdn的鏈接 developer.mozilla.org/zh-CN/docs/…[1]

webworkerhtml5的一個api,它的作用就是新開一個線程去做一些操作,因為這個線程并不會阻塞主線程,所以可以去提高網頁的性能。其實可以把他當成一個函數,傳參進行計算得到你想要經過一些代碼處理的東西。

Demo

這里就以計算計算斐波那契數列為例子去給大家演示。

主線程腳本(index.html)

在主線程中 new一個worker對象,傳參的是一個js腳本路徑,不能傳其他類型的文本,也必須是同源的。然后通過message事件和postmessage進行通信即可。

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF - 8">
<title>demo</title>
</head>

<body>
<button onclick="startCalculation()">斐波那契數列</button>
<p id="result"></p>
<script>
    function startCalculation({
      // 創建一個Web Worker對象,指定worker.js作為工作線程的腳本
      const worker = new Worker('worker.js');
      worker.postMessage(20)
      // 監聽工作線程發送的消息
      worker.onmessage = function (event{
        document.getElementById('result').innerHTML = '斐波那契數列的第20項是:' + event.data;
          // 通知關閉線程
          worker.postMessage('close')
      };
    }
  
</script>
</body>

</html>

工作線程(work.js)

這里主要的點是self,在工作線程中的self就相當于主線程的window,也就是window中很多東西在self中也能使用。但是工作線程是沒有去獲取dom的權限的,所以他不能也不建議去操作dom。然后就是通過message和postMessage去通信。

// 計算斐波那契數列的函數
function feibo(n{
if (n === 0 || n === 1) {
    return n;
  }
return feibo(n - 1) + feibo(n - 2);
}

// 計算斐波那契數列的第10項并發送結果給主線程
self.onmessage = function (e{
console.log(e.data);
if(e.data == 'close') {
      // 關閉線程
      self.close()
      return
  }
const data = feibo(e.data);
  self.postMessage(data);
};

方法屬性

  1. self

self是對工作線程自身全局對象的引用。類似于瀏覽器主線程中的window對象,要注意的self不能訪問 DOM 相關內容

  1. postmessge和message

當主線程使用worker.postMessage發送消息時,工作線程中的message事件處理函數就會被觸發。當工作線程使用worker.postMessage發送消息時,主線程中的message事件處理函數就會被觸發。所以就是用來通信的

  1. importScripts

用于在工作線程中加載外部腳本。可以同時加載多個腳本,并且腳本會按照它們在importScripts函數參數中的順序依次加載,不過我感覺這個方法應該很少用。

  1. terminate(在線程中使用)
worker.terminate();
  1. close (在工作線程中使用)
self.colse();

是吧。其實webworker就這么點東西,就是相當一個裝機師傅,你把主板,cpu,顯卡,內存,風扇...給他,師傅就可以還給你一臺主機。然后我在用的時候就發現會有一些,就會導致出現bug。

坑1:postMessage

不知道大家知不知道,postMessage是一種異步通信。什么叫異步通信呢。就是我給你通知了,但是我不會去等你執行代碼,我繼續執行我的代碼。大家可以用上面的demo試一下。我一開始以為是和我們vue的組件自定義事件通信那樣,是同步通信的。其實應該很多人都不知道這個是同步通信的,這個很重要的,工作中不注意這個時機,就會導致bug,我記得我在面試的時候也被問到過。我下面寫了個vue3的自定義通信的小demo,然后在自定義事件中寫了for循環阻塞5秒鐘,大家可以復制跑一下看看。

parent.vue

<template>
  <Child @chageFn="chageFn"></Child>
</template>

<script setup>
import Child from "./child.vue";
const chageFn = () => {
  const start = Date.now();
  const waitTime = 5000// 5秒,單位是毫秒
  for (let i = 0Date.now() - start < waitTime; i++) {

  }
  console.log("5秒時間已過,繼續執行后續代碼");
};
</script>
<style lang="scss" scoped></style>

child.vue

<template>
  <button @click="clickFn">點擊我</button>
</template>

<script setup>
import { defineEmits } from "vue";
const emit = defineEmits(["chageFn"]);
const clickFn = () => {
  emit("chageFn");
  console.log("1");
};
</script>
<style lang="scss" scoped></style>

當我們點擊的時候就可以發現,是在五秒后打印1,并不會立即打印1,但如果是postMessage通信是會立即打印1的。然后這個同步通信并不是說一定會等自定義函數執行完才會走后面的代碼,如果這個自定義函數中是異步代碼,是會先打印1的,就是正常的事件循環機制,大家也可以試試。

坑2:序列化和反序列化

postMessage在進行通信時會對數據進行序列化的,在message事件接收數據是會反序列的,啥意思呢,就是類似于JSON.parse和JSON.stringify,這兩個api就是將js的數據類型轉化成JSON格式的數據,但是postMessage并不是轉化成JSON格式,它是一種結構化克隆算法,具體我也不清楚。他們的共同點都是不能轉化函數,JSON.stringify是會將函數變成undefind,postMessage是報錯。

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Worker Function and Circular Reference Example</title>
</head>

<body>
<script>
    const fn = ()=>{
        console.log(1)
    }
    console.log(JSON.stringify(fn)) // undefind 

    const worker = new Worker('worker.js')
    worker.postMessage(fn) // 報錯
  
</script>
</body>

</html>

坑3:如何正確的去通信以及正確的去關閉工作線程

當我們使用webworker的時候不可能說每使用一次就new一次webwoker,而是每次都是使用這一個線程進行處理。然后可能會導致什么問題呢?還是那個裝機師傅的例子,有兩個人同時去找這個師傅裝機,裝完了師傅不知道這兩個機子分別是誰的。那師傅肯定沒有這么笨,他肯定會貼個標簽說這個是他的,那個是她的。所以,當我們通信的時候就需要去規定通信的格式。比如下面這樣,當主線程給工作線程通信的時候,傳一個id字段實現唯一性,當工作線程回復的時候也帶上這個字段,大家具體情況具體分析。

const params = {
    id:"1",
    params:{

    }
}

const response = {
    id:"1",
    data:{
                
    }
}

關閉工作線程是有兩種方式的,一種是主線程去關閉,另一種是工作線程自己關閉。如果協調不好的話就可能會導致工作線程的代碼并沒有執行完成就關閉了,然后就會引出很多問題。不過這個我倒是沒遇到過hhh,其實我覺得可以去統一一下關閉的地方。比如,統一由主線程去關閉,當工作線程想關閉的時候,去通過postmessage去通知主線程去關閉。

總結

我覺得webworker其實大部分前端應該是很少用到的,反正我是第一次用。不過也并不是很難,稍微看一下就能學會,就能使用在工作上了。這應該也只會在性能優化的時候去使用,畢竟在大多數情況下封裝函數就行了,誰會想著新開一個線程去處理,麻煩死了。只能說,技多不壓身,學不死就往死里學!


閱讀原文:原文鏈接


該文章在 2025/1/7 11:31:07 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
亚洲欧美日韩国产一区 | 中文字幕一区二区在线观看 | 日韩精品一区二区三区在线 | 亚洲日本精品一区二区高清 | 小早川怜子国内精品久久久久 | 亚洲欧美日韩国产综合第二页 |