日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

精读《谈谈 Web Workers》

發(fā)布時間:2025/3/8 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 精读《谈谈 Web Workers》 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 引言

本周精讀的文章是 speedy-introduction-to-web-workers,是一篇 Web Workers 快速入門的文章,借精讀這篇文章的機會,談談對 Web Workers 的理解與運用。

2 概述

就像分工,你只負責編碼,而你的朋友負責設計,那你就可以專心把自己的事情做好,而且更快速的完成任務。

本文通過一個比方,描述了 Web Workers 的兩大特征:

  • 高效。
  • 并行。
  • 因為瀏覽器是單線程的,任何大量耗時的 JS 任務都會卡住界面,使瀏覽器無法響應任何操作,這樣的用戶體驗非常糟糕。Web Workers 可以將耗時任務拆解出去,降低主線程的壓力,避免主線程無響應。

    但 CPU 資源是有限的,Web Workers 并不能增加總體運行效率,算上通信的損耗,整體計算效率會有一定的下降。

    創(chuàng)建 Web Workers

    const worker = new Worker("../src/worker.js"); 復制代碼

    上述代碼中,worker 就是一個 Web Workers 實例,執(zhí)行的代碼是 ../src/worker.js 路徑下的文件。

    收發(fā)消息

    Web Workers 用來執(zhí)行異步腳本,只要掌握了它與主線程通信的方式,就可以在指定時機運行異步腳本,并在運行完時將結果傳遞給主線程。

    主線程接收發(fā) Web Workers 消息

    const worker = new Worker("../src/worker.js");worker.onmessage = e => {};worker.postMessage("Marco!"); 復制代碼

    每個 worker 實例通過 onmessage 接收消息,通過 postMessage 發(fā)送消息。

    Web Workers 收發(fā)主線程消息

    self.onmessage = e => {};self.postMessage("Marco!"); 復制代碼

    和主線程代碼類似,在 Web Workers 代碼中,也是 onmessage 接收消息,這個消息來自主線程或者其它 Workers。也可以通過 postMessage 發(fā)送消息。

    銷毀 Web Workers

    worker.terminate(); 復制代碼

    文章內容就這么多,是不是有寫太簡單了呢!筆者結合自己的使用經驗,再補充一些知識。

    3 精讀

    對象轉移(Transferable Objects)

    對象轉移就是將對象引用零成本轉交給 Web Workers 的上下文,而不需要進行結構拷貝。

    這里要解釋的是,主線程與 Web Workers 之間的通信,并不是對象引用的傳遞,而是序列化/反序列化的過程,當對象非常龐大時,序列化和反序列化都會消耗大量計算資源,降低運行速度。

    上面的圖充分證明了,大對象傳遞,使用對象轉移各項指標都優(yōu)于結構拷貝。

    對象轉移使用方式很簡單,給 postMessage 增加一個參數(shù),把對象引用傳過去即可:

    var ab = new ArrayBuffer(1); worker.postMessage(ab, [ab]); 復制代碼

    瀏覽器兼容性也不錯:Currently Chrome 17+, Firefox, Opera, Safari, IE10+。更具體內容,可以看 Transferable Objects: Lightning Fast!。

    需要注意的是,對象引用轉移后,原先上下文就無法訪問此對象了,需要在 Web Workers 再次將對象還原到主線程上下文后,主線程才能正常訪問被轉交的對象。

    如何不用 JS 文件創(chuàng)建 Web Workers

    Web Workers 優(yōu)勢這么大,但用起來需要在同域下創(chuàng)建一個 JS 文件實在不方便,尤其在前后端分離做的比較徹底的團隊,前端團隊能控制的僅僅是一個 JS 文件。那么下面給出幾個不用 JS 文件,就創(chuàng)建 Web Workers 的方法:

    webpack 插件 - worker-loader

    worker-loader 是一個 webpack 插件,可以將一個普通 JS 文件的全部依賴提取后打包并替換調用處,以 Blob 形式內聯(lián)在源碼中。

    import Worker from "worker-loader!./file.worker.js";const worker = new Worker(); 復制代碼

    上述代碼的魔術在于,轉化成下面的方式執(zhí)行:

    const blob = new Blob([codeFromFileWorker], { type: "application/javascript" }); const worker = new Worker(URL.createObjectURL(blob)); 復制代碼

    Blob URL

    第二種方式由第一種方式自然帶出:如果不想用 webpack 插件,那自己通過 Blob 的方式創(chuàng)建也可以:

    const code = `importScripts('https://xxx.com/xxx.js');self.onmessage = e => {}; `;const blob = new Blob([code], { type: "application/javascript" }); const worker = new Worker(URL.createObjectURL(blob)); 復制代碼

    看上去代碼更輕量一些,不過問題是當遇到復雜依賴時,如果不能把依賴都轉化為腳本通過 importScripts 方式引用,就無法訪問到主線程環(huán)境中的包。如果真的遇到了這個問題,可以用第一種 webpack 插件的方式解決,這個插件會自動把文件所有依賴都打包進源碼。

    管理 postMessage 隊列

    為什么 postMessage 會形成隊列,為什么要管理它?

    首先在 Web Workers 架構設計上就必須做成隊列,因為調用 postMessage 時,對應的 Web Workers 不一定完成了初始化,所以瀏覽器底層必須管理一個隊列,在 Web Workers 初始化完畢時,依次消費,這樣才能確保任何時候發(fā)出的 postMessage 都能被 Web Workers 接收到。

    其次,為什么要手動維護這個隊列,原因可能取決于如下幾點:

    • 業(yè)務原因,前面的 postMessage 還沒來得及消費,就不要發(fā)送新的消息,或者丟棄新的消息,這時候需要通過雙向通信拿到 Web Workers 的執(zhí)行結果回執(zhí),手動控制隊列。
    • 性能原因,一般 Web Workers 都會被用來執(zhí)行耗時的同步運算,如果運算時間比較長,那短期塞入多個消息隊列是沒有意義的。

    如上圖所示,對于每次用戶輸入都要進行的 SQL Parser 很耗時,及時放在 Web Workers 也可能導致將 Workers 撐爆到無響應,這是不僅要使用多 Workers 緩沖池,還要對待執(zhí)行隊列進行過濾,因為用戶永遠只關心最后一次輸入的 Parser 結果。

    由于 Web Workers 運算被卡住時,除了銷毀 Worker 沒有別的辦法,而銷毀 Worker 的成本比較高,不能對每一個用戶輸入都銷毀并新建 Web Workers,所以利用 Workers 緩沖池,當緩沖池滿了,新的消費隊列又進來的時候,可以銷毀全部 Workers 緩沖池,換一批新緩沖池重新消費用戶輸入。

    4 總結

    Web Workers 是拆解異步計算的好幫手,vscode 網頁版也通過 Web Workers 異步完成代碼提示和高亮,筆者有對比過,發(fā)現(xiàn) Web Workers 性能提升非常明顯。

    管理好你的 Web Workers 消息隊列,謹防同步計算讓 Web Workers 失去響應!建立一個智能的消息隊列,根據(jù)業(yè)務需求設計一個最好的隊列消費模型吧!

    5 更多討論

    討論地址是:精讀《談談 Web Workers》 · Issue #108 · dt-fe/weekly

    如果你想?yún)⑴c討論,請點擊這里,每周都有新的主題,周末或周一發(fā)布。前端精讀 - 幫你篩選靠譜的內容。

    總結

    以上是生活随笔為你收集整理的精读《谈谈 Web Workers》的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。