TypeScript 中的網頁工作者

TypeScript 中的網頁工作者

本文介紹了 TypeScript 中的網頁工作者。

您可以學習 Web Workers 的概念以及各種使用技巧,並附有範例說明。

YouTube Video

TypeScript 中的工作者

在 TypeScript 中,Worker 是一種機制,用於在後台執行處理,獨立於主執行緒,並利用 JavaScript 的網頁工作者 (Web Workers) API。這使得繁重的計算和異步任務可以執行,而不影響使用者介面的操作。

Worker 與主執行緒(UI 執行緒)並行運作,並能透過訊息在執行緒之間交換資料。即使在 TypeScript 中,也可以使用 Worker 來編寫類型安全的程式碼。

工作者的基本用法

  1. 創建一個 Worker

    創建一個 Worker 實例並執行指定的腳本。通常,腳本定義在一個單獨的檔案中。

  2. 訊息交換

    通過 postMessageonmessage 在主執行緒和 Worker 執行緒之間傳送和接收訊息。

範例:基本的 Worker 實現

  1. worker.ts:Worker 的腳本
1// worker.ts
2self.onmessage = (event) => {
3    const data = event.data;
4    const result = data.num1 + data.num2;
5    self.postMessage(result); // Return the result to the main thread
6};
  1. main.ts:在主執行緒中使用 Worker 的腳本
 1// main.ts
 2const worker = new Worker(
 3    new URL('./worker.ts', import.meta.url),
 4    { type: 'module' }
 5);
 6
 7worker.onmessage = (event) => {
 8    console.log("Result from worker:", event.data); // Receive message from the worker
 9};
10
11worker.postMessage({ num1: 10, num2: 20 }); // Send message to the worker
  • 在此範例中,worker.ts 在單獨的執行緒中運行,計算 num1num2 的總和,並將結果返回給主執行緒。主執行緒接收結果並將其輸出到控制台。
  • 當你指定 type: 'module' 時,Worker 腳本會被解讀為 ES 模組,允許你使用 importexport。這讓你可以在不使用傳統 importScripts() 的情況下處理模組結構。

在 TypeScript 中使用 Workers 時需要注意的要點

添加類型定義

在 TypeScript 中,定義資料類型以確保訊息傳遞和接收期間的類型安全互動。

 1// Define data types
 2interface WorkerData {
 3    num1: number;
 4    num2: number;
 5}
 6
 7interface WorkerResult {
 8    result: number;
 9}
10
11// worker.ts
12self.onmessage = (event: MessageEvent<WorkerData>) => {
13    const data = event.data;
14    const result = data.num1 + data.num2;
15    const message: WorkerResult = { result };
16    self.postMessage(message); // Send the result in a type-safe manner
17};
18
19// main.ts
20const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
21
22// Type the event from the worker
23worker.onmessage = (event: MessageEvent<WorkerResult>) => {
24  console.log("Result from worker:", event.data); // event.data is number
25};
26
27// Send typed data to the worker
28const message: WorkerData = { num1: 10, num2: 20 };
29worker.postMessage(message);
  • 通過指定 MessageEvent 的類型參數,可以清楚地定義要接收的資料類型。這允許以類型安全的方式交換資料。

設置 Webpack 或 Vite

在 TypeScript 中使用 Worker 時,可能需要使用像 WebpackVite 之類的打包工具。通過使用這些工具,您可以正確地打包 Worker 腳本,並讓主執行緒可以使用。

例如,在使用 Vite 時,可以使用 import.meta.url 來正確導入 Worker

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
  • 這確保了打包後的 Worker 腳本能夠正確加載,從而實現使用 Worker 進行處理。

關於訊息傳遞和並行處理的考量

  1. 資料複製

    當主執行緒與 Worker 執行緒之間進行訊息傳遞時,資料是以複製的方式傳輸的。處理像物件這樣的複雜資料時,需考慮效率問題。頻繁地交換大量資料會降低效能。

  2. Transferable 對象

    有些物件,比如 ArrayBuffer,被稱為 Transferable 可轉移物件。Transferable 可轉移物件在傳遞訊息時可以直接轉移給 Worker,而不是複製。這可以避免資料複製帶來的額外負擔。

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3const buffer = new ArrayBuffer(1024);
4worker.postMessage(buffer, [buffer]); // Transfer ownership to the Worker
5
6console.log(buffer.byteLength); // 0 (ownership moved)
  • worker.postMessage() 中傳遞 [buffer] 作為第二個參數,buffer 會被轉移給 Worker,而不是被複製。

  • 之後,主執行緒上的 buffer 會變成空的(byteLength 為 0),只能由 Worker 使用。

中止一個 Worker

在使用完 Worker 後應將其中止以減少記憶體消耗。您可以使用 terminate 方法來中止一個 Worker

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2// ...
3
4worker.terminate(); // Terminate the Worker
  • 這段程式碼使用 terminate 方法來終止 Worker。

在 Worker 中的例外處理

如果有錯誤發生在 Worker 中,您可以使用 onerror 事件來處理該錯誤。

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3worker.onerror = (error) => {
4    console.error("Error in Worker:", error.message);
5};
  • 這段程式碼通過 onerror 事件來捕捉並處理 Worker 內部發生的錯誤。

總結

在 TypeScript 中使用 Worker,您可以在後台執行繁重任務,同時保持主執行緒的流暢運作。通過使用類型定義,訊息交換也可以以類型安全的方式進行。通過注重資料交換和執行緒管理,您可以實現效能提升與高效的並行處理。

您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。

YouTube Video