国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

精讀《談談 Web Workers》

myeveryheart / 1397人閱讀

摘要:可以將耗時任務拆解出去,降低主線程的壓力,避免主線程無響應。主線程接收發消息每個實例通過接收消息,通過發送消息。收發主線程消息和主線程代碼類似,在代碼中,也是接收消息,這個消息來自主線程或者其它。

1 引言

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

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

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

高效。

并行。

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

但 CPU 資源是有限的,Web Workers 并不能增加總體運行效率,算上通信的損耗,整體計算效率會有一定的下降。
創建 Web Workers
const worker = new Worker("../src/worker.js");

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

收發消息

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

主線程接收發 Web Workers 消息
const worker = new Worker("../src/worker.js");

worker.onmessage = e => {};

worker.postMessage("Marco!");

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

Web Workers 收發主線程消息
self.onmessage = e => {};

self.postMessage("Marco!");

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

銷毀 Web Workers
worker.terminate();

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

3 精讀 對象轉移(Transferable Objects)

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

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

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

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

var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);

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

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

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

webpack 插件 - worker-loader

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

import Worker from "worker-loader!./file.worker.js";

const worker = new Worker();

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

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

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

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 方式引用,就無法訪問到主線程環境中的包。如果真的遇到了這個問題,可以用第一種 webpack 插件的方式解決,這個插件會自動把文件所有依賴都打包進源碼。

管理 postMessage 隊列

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

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

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

業務原因,前面的 postMessage 還沒來得及消費,就不要發送新的消息,或者丟棄新的消息,這時候需要通過雙向通信拿到 Web Workers 的執行結果回執,手動控制隊列。

性能原因,一般 Web Workers 都會被用來執行耗時的同步運算,如果運算時間比較長,那短期塞入多個消息隊列是沒有意義的。

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

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

4 總結

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

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

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

如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。前端精讀 - 幫你篩選靠譜的內容。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98545.html

相關文章

  • 如何機制地回答瀏覽器兼容性問題

    摘要:前言有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如何才是我們正確回答這個問題的姿勢呢。 前言 有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如...

    leanote 評論0 收藏0
  • 如何機制地回答瀏覽器兼容性問題

    摘要:前言有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如何才是我們正確回答這個問題的姿勢呢。 前言 有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如...

    Rindia 評論0 收藏0
  • 精讀《Monorepo 的優勢》

    摘要:引言本周精讀的文章是。精讀總的來說,雖然拆分子倉庫拆分子包是進行項目隔離的天然方案,但當倉庫內容出現關聯時,沒有任何一種調試方式比源碼放在一起更高效。前端精讀幫你篩選靠譜的內容。 1. 引言 本周精讀的文章是 The many Benefits of Using a Monorepo。 現在介紹 Monorepo 的文章很多,可以分為如下幾類:直接介紹 Lerna API 的;介紹如何...

    xcc3641 評論0 收藏0
  • 精讀《現代 js 框架存在的根本原因》

    摘要:官方規范估計很難出現現代框架的設計了,因為官方設計中前端三劍客是相互分離的方案,為了解決現階段前端框架的問題,必須由完全接管,這幾乎就是,或者支持語法的,可這與最初網頁設計思路是違背的。現代前端框架正在告訴我們新的三劍客虛擬虛擬。 1 引言 深入思考為何前端需要框架,以及 web components 是否可以代替前端框架? 原文地址,建議先閱讀原文,或者閱讀概述。 2 概述 現在前端...

    coordinate35 評論0 收藏0

發表評論

0條評論

myeveryheart

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<