精品秘无码一区二区三区老师-精品秘一区二三区免费雷安-精品蜜桃秘一区二区三区-精品蜜桃秘一区二区三区粉嫩-精品蜜桃一区二区三区-精品蜜臀国产aⅴ一区二区三区

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

不會(huì)webworker,你做什么前端性能優(yōu)化?

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

作者:落課

https://juejin.cn/post/7433719237455937546


前言

本來(lái)這篇文章是打算寫我之前那個(gè)迭代首屏優(yōu)化的,但是我做的那些優(yōu)化,前幾天上了生產(chǎn),效果并不如意,因?yàn)樯a(chǎn)環(huán)境不能隨便動(dòng),我只能在灰度環(huán)境上測(cè)試,但是灰度測(cè)試后確實(shí)是比之前好的。那篇文章我也寫了大半了,過(guò)幾天發(fā)出來(lái)大家指點(diǎn)一下。然后我最近看了評(píng)論想著使用webworker去優(yōu)化一下我那坨列表,然后我之前也沒(méi)用過(guò),最近也研究了一下,所以這篇文章就給大家分享一下webworker怎么用。其實(shí)挺簡(jiǎn)單的,但是遇到了一些坑!希望大家使用的時(shí)候能注意一下。

什么是web worker?

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

webworkerhtml5的一個(gè)api,它的作用就是新開(kāi)一個(gè)線程去做一些操作,因?yàn)檫@個(gè)線程并不會(huì)阻塞主線程,所以可以去提高網(wǎng)頁(yè)的性能。其實(shí)可以把他當(dāng)成一個(gè)函數(shù),傳參進(jìn)行計(jì)算得到你想要經(jīng)過(guò)一些代碼處理的東西。

Demo

這里就以計(jì)算計(jì)算斐波那契數(shù)列為例子去給大家演示。

主線程腳本(index.html)

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

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

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

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

</html>

工作線程(work.js)

這里主要的點(diǎn)是self,在工作線程中的self就相當(dāng)于主線程的window,也就是window中很多東西在self中也能使用。但是工作線程是沒(méi)有去獲取dom的權(quán)限的,所以他不能也不建議去操作dom。然后就是通過(guò)message和postMessage去通信。

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

// 計(jì)算斐波那契數(shù)列的第10項(xiàng)并發(fā)送結(jié)果給主線程
self.onmessage = function (e{
console.log(e.data);
if(e.data == 'close') {
      // 關(guān)閉線程
      self.close()
      return
  }
const data = feibo(e.data);
  self.postMessage(data);
};

方法屬性

  1. self

self是對(duì)工作線程自身全局對(duì)象的引用。類似于瀏覽器主線程中的window對(duì)象,要注意的self不能訪問(wèn) DOM 相關(guān)內(nèi)容

  1. postmessge和message

當(dāng)主線程使用worker.postMessage發(fā)送消息時(shí),工作線程中的message事件處理函數(shù)就會(huì)被觸發(fā)。當(dāng)工作線程使用worker.postMessage發(fā)送消息時(shí),主線程中的message事件處理函數(shù)就會(huì)被觸發(fā)。所以就是用來(lái)通信的

  1. importScripts

用于在工作線程中加載外部腳本。可以同時(shí)加載多個(gè)腳本,并且腳本會(huì)按照它們?cè)?/span>importScripts函數(shù)參數(shù)中的順序依次加載,不過(guò)我感覺(jué)這個(gè)方法應(yīng)該很少用。

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

是吧。其實(shí)webworker就這么點(diǎn)東西,就是相當(dāng)一個(gè)裝機(jī)師傅,你把主板,cpu,顯卡,內(nèi)存,風(fēng)扇...給他,師傅就可以還給你一臺(tái)主機(jī)。然后我在用的時(shí)候就發(fā)現(xiàn)會(huì)有一些,就會(huì)導(dǎo)致出現(xiàn)bug。

坑1:postMessage

不知道大家知不知道,postMessage是一種異步通信。什么叫異步通信呢。就是我給你通知了,但是我不會(huì)去等你執(zhí)行代碼,我繼續(xù)執(zhí)行我的代碼。大家可以用上面的demo試一下。我一開(kāi)始以為是和我們vue的組件自定義事件通信那樣,是同步通信的。其實(shí)應(yīng)該很多人都不知道這個(gè)是同步通信的,這個(gè)很重要的,工作中不注意這個(gè)時(shí)機(jī),就會(huì)導(dǎo)致bug,我記得我在面試的時(shí)候也被問(wèn)到過(guò)。我下面寫了個(gè)vue3的自定義通信的小demo,然后在自定義事件中寫了for循環(huán)阻塞5秒鐘,大家可以復(fù)制跑一下看看。

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秒時(shí)間已過(guò),繼續(xù)執(zhí)行后續(xù)代碼");
};
</script>
<style lang="scss" scoped></style>

child.vue

<template>
  <button @click="clickFn">點(diǎn)擊我</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>

當(dāng)我們點(diǎn)擊的時(shí)候就可以發(fā)現(xiàn),是在五秒后打印1,并不會(huì)立即打印1,但如果是postMessage通信是會(huì)立即打印1的。然后這個(gè)同步通信并不是說(shuō)一定會(huì)等自定義函數(shù)執(zhí)行完才會(huì)走后面的代碼,如果這個(gè)自定義函數(shù)中是異步代碼,是會(huì)先打印1的,就是正常的事件循環(huán)機(jī)制,大家也可以試試。

坑2:序列化和反序列化

postMessage在進(jìn)行通信時(shí)會(huì)對(duì)數(shù)據(jù)進(jìn)行序列化的,在message事件接收數(shù)據(jù)是會(huì)反序列的,啥意思呢,就是類似于JSON.parse和JSON.stringify,這兩個(gè)api就是將js的數(shù)據(jù)類型轉(zhuǎn)化成JSON格式的數(shù)據(jù),但是postMessage并不是轉(zhuǎn)化成JSON格式,它是一種結(jié)構(gòu)化克隆算法,具體我也不清楚。他們的共同點(diǎn)都是不能轉(zhuǎn)化函數(shù),JSON.stringify是會(huì)將函數(shù)變成undefind,postMessage是報(bào)錯(cuò)。

<!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) // 報(bào)錯(cuò)
  
</script>
</body>

</html>

坑3:如何正確的去通信以及正確的去關(guān)閉工作線程

當(dāng)我們使用webworker的時(shí)候不可能說(shuō)每使用一次就new一次webwoker,而是每次都是使用這一個(gè)線程進(jìn)行處理。然后可能會(huì)導(dǎo)致什么問(wèn)題呢?還是那個(gè)裝機(jī)師傅的例子,有兩個(gè)人同時(shí)去找這個(gè)師傅裝機(jī),裝完了師傅不知道這兩個(gè)機(jī)子分別是誰(shuí)的。那師傅肯定沒(méi)有這么笨,他肯定會(huì)貼個(gè)標(biāo)簽說(shuō)這個(gè)是他的,那個(gè)是她的。所以,當(dāng)我們通信的時(shí)候就需要去規(guī)定通信的格式。比如下面這樣,當(dāng)主線程給工作線程通信的時(shí)候,傳一個(gè)id字段實(shí)現(xiàn)唯一性,當(dāng)工作線程回復(fù)的時(shí)候也帶上這個(gè)字段,大家具體情況具體分析。

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

    }
}

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

關(guān)閉工作線程是有兩種方式的,一種是主線程去關(guān)閉,另一種是工作線程自己關(guān)閉。如果協(xié)調(diào)不好的話就可能會(huì)導(dǎo)致工作線程的代碼并沒(méi)有執(zhí)行完成就關(guān)閉了,然后就會(huì)引出很多問(wèn)題。不過(guò)這個(gè)我倒是沒(méi)遇到過(guò)hhh,其實(shí)我覺(jué)得可以去統(tǒng)一一下關(guān)閉的地方。比如,統(tǒng)一由主線程去關(guān)閉,當(dāng)工作線程想關(guān)閉的時(shí)候,去通過(guò)postmessage去通知主線程去關(guān)閉。

總結(jié)

我覺(jué)得webworker其實(shí)大部分前端應(yīng)該是很少用到的,反正我是第一次用。不過(guò)也并不是很難,稍微看一下就能學(xué)會(huì),就能使用在工作上了。這應(yīng)該也只會(huì)在性能優(yōu)化的時(shí)候去使用,畢竟在大多數(shù)情況下封裝函數(shù)就行了,誰(shuí)會(huì)想著新開(kāi)一個(gè)線程去處理,麻煩死了。只能說(shuō),技多不壓身,學(xué)不死就往死里學(xué)!


閱讀原文:原文鏈接


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

主站蜘蛛池模板: 亚洲永久免费精品高清 | 国产69精品久久久久乱码免费 | 亚洲国产成人av在线电影 | 成人h无码动漫超w网站 | 国产女合集小岁9三部 | 亚洲欧洲无码一区二区三区 | 国产三级视频在线 | 日日草夜夜操 | 午夜福到在线4国产社 | 亚洲电影院男人的天堂 | 亚洲自拍另类 | 日韩精品中文字幕无码专区 | 午夜全免费一级毛片在线播放 | 亚洲男同志网站 | 国产欧美日韩一区二区三区在线 | 亚洲午夜精品 | 女同性av片在线观看免费网站 | 国产成人精品视频午夜 | 亚洲日本免费 | 一区二区三区欧美午夜视频 | 四虎永久在线精品免费观看视频 | 精品视频在线观看免费 | 午夜无码不卡中文字幕最 | 麻豆www久久国产精品 | 亚洲欧美人成网站综合在线 | 内射一区二区精品视频在线 | 蜜臀av 国内精品久久久 | 自拍偷拍亚洲精品 | 毛片无码视频中字 | 无套内谢少妇毛片A片999 | 久久精品国产亚洲av高清热 | 国产精品大尺度尺度视频 | 成人中文国产手机免费 | 免费的青榴视频在线观看 | 亚洲乱码日产精品bd在线观看 | 亚洲精品久久久久久久久久吃药 | 国产成人久久精品一区二区三 | 成人国产亚洲欧美一区 | 久久精品国产亚洲av网站 | 不卡无码人妻一区三区音频 | 日韩欧美一区二区三区不卡在 |