首頁  >  文章  >  web前端  >  開始之前您需要了解的有關 Web Worker 的所有資訊。

開始之前您需要了解的有關 Web Worker 的所有資訊。

DDD
DDD原創
2024-10-31 21:07:29911瀏覽

最近我一直在研究 Web Worker,這是一份全面的指南,涵蓋了開始使用 Web Worker 所需了解的所有內容。

如果您想跳過閱讀部落格並查看程式碼,這裡是包含所有程式碼片段的 github 儲存庫。

Github Web Worker 儲存庫

 

目錄

  • 常見誤解
  • Web Worker 基本設定
    • 使用本機 JavaScript 設定 Web Worker
    • 使用 Comlink 設定 Web Workers
  • 如何檢查我的工人是否已正確註冊?
  • 延伸閱讀

 
 

常見的誤解

所以,促使我探索 Web Workers 的原因是,在我建立的平台中,一項計算繁重的任務會阻塞 UI。
所以我想,『嗯,好吧,我該如何讓它不阻塞 UI』?我是否應該使用 setTimeout 來確保主線程中的所有程式碼都已執行完畢,然後才能運行計算量大的任務?

所以這是一個誤解-使用setTimeout並不代表UI不會被阻塞。是的,主執行緒上的所有內容都會在 setTimeout 回呼運行之前執行,但是,當該回呼從巨集任務佇列中彈出時,它會在主執行緒本身中運行,從而使 UI 無回應。

要了解更多有關 setTimeout 如何運作的信息,請參考一些參考資料 —

  • 從頭開始的非同步 JavaScript 和事件循環 - Akshay Saini
  • 事件循環、Web API、任務佇列 - Lydia Hallie

 
 

Web Worker 基本設定

JavaScript 本質上是一種“單執行緒語言”,但是 Web Worker 使我們能夠在單獨的執行緒中運行計算量大的程式碼。

在開始之前,有幾件事要注意 -

  • Web Worker 無法與 DOM 互動
  • Web Worker 作用域是 self,而不是 window。
  • Workers 相對較重,不適合大量使用。例如,為四兆像素影像的每個像素啟動一名工作人員是不合適的。 [參考 - HTML 規範]
  • 此外,Web Worker 並不是要讓某件事需要 2 秒而不是 4 秒,而是要在 DOM 凍結 0 秒的情況下完成這件事。 [參考 - Web Workers 很慢,沒關係 - Calvin Metcalf]
  • 工作人員可能會產生新的工作人員,只要這些工作人員託管在與父頁面相同的來源中。 [參考 - MDN]

 

使用原生 JavaScript 的 Web Worker

  1. 建立一個新的 JavaScript 文件,其中包含要在工作執行緒中執行的程式碼。 (如worker.js)
  2. 在主腳本中實例化worker -
const worker = new Worker("./worker.js")

注意:worker.js 不是一個模組,不能使用 import 語句。然而。 :')

要將worker.js當作模組,請在建構子的選項中指定type: module。

const worker = new Worker("./worker.js")
  1. 資料透過訊息系統在工作人員之間發送 - 雙方都使用 postMessage() 方法發送訊息,並透過 onmessage 事件處理程序回應訊息
  2. 要在 postMessage() 中傳遞具有循環參考的複雜對象,請使用 StructuredClone 方法。
  3. 要終止 Web Worker,請使用 Worker API 的終止方法。這並不為工人提供完成其正在進行的操作的機會;它立即停止。
const worker = new Worker('./worker.js', { type: 'module' })

 
把它們放在一起

現在,讓我們看看整合 Web Worker 後我們的程式碼是什麼樣子。

主執行緒程式碼:

worker.terminate() 

工作執行緒程式碼:

// ...
function workerFunction() {
  // Don't spin up a new worker instance if the process has already been started.
  if (statusElement.textContent !== PROCESS_STATUS.PROCESSING && window.Worker) {
    const worker = new Worker('./worker.js', {
      type: 'module'
    })

    // Sending 10000000000000 to the web worker
    worker.postMessage(10000000000000)

    statusElement.textContent = PROCESS_STATUS.PROCESSING

    // This piece of code is executed after worker finishes its task and returns data. 
    worker.onmessage = function (event) {
      statusElement.textContent = event.data
    }
  }
}
// ...

結果:

當我們執行應用程式時,您會注意到執行計算量大的任務時不會阻塞 UI。

 

使用 Comlink 設定 Web Worker

Comlink 是一個小型庫(1.1kB),它消除了思考 postMessage 邏輯的心理障礙。

在更抽象的層面上,它是 postMessage 和 ES6 代理程式的 RPC 實作。

我使用 Comlink 的一個具體原因是我無法使用純 JavaScript 將函數從主執行緒傳遞到工作執行緒。使用 Comlink 的代理,我能夠輕鬆地將回呼函數從主執行緒傳遞到工作執行緒。 [參考此部分]

要開始在專案中使用 comlink,請安裝庫

const worker = new Worker("./worker.js")

要開始使用這個函式庫,我們需要了解以下這些方法 -

Comlink.wrap(端點)

  • 包裝工作人員公開的對象,返回一個代理,您可以像本地對像一樣與之交互。
  • 代理將具有公開值的所有屬性和功能,但存取和呼叫本質上是非同步的。即,如果函數傳回一個數字,它現在將傳回該數字的承諾。
const worker = new Worker('./worker.js', { type: 'module' })

Comlink.expose(值、端點?、allowedOrigins?)

  • 暴露函數將值從一個執行緒暴露給另一個執行緒(即將物件從工作執行緒暴露給主執行緒)
worker.terminate() 

 

如何檢查我的工人是否已正確註冊?

  • 檢查工作文件是否已在網頁瀏覽器中註冊(我使用的是 Chrome)
  • 右鍵單擊→檢查,然後轉到來源面板,您將在其中找到工作文件。
  • 終止後,工作文件不應在「來源」面板中可見
  • 如果您在終止工作人員後仍然可以看到工作人員文件,那麼很可能您已經註冊了多個工作人員,但並非所有工作人員都已被終止。

All you need to know about web workers to get started.

 


延伸閱讀
  • 傳輸處理程序與事件監聽器
  • 共享工作者
  • 可轉讓物品



以上是開始之前您需要了解的有關 Web Worker 的所有資訊。的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn