HTML - Web Workers API



HTML Web Workers API 是一個 JavaScript 特性,用於在後臺的單獨執行緒中執行計算密集型任務,而不會中斷使用者介面。

在本 Web Workers API 章節中,您將學習以下主題

什麼是 Web Workers?

  • Web Workers 允許執行長時間任務而不會讓頁面失去響應。
  • Web Workers 是後臺指令碼,它們相對重量級,不適合大量使用。例如,為四百萬畫素影像的每個畫素啟動一個工作執行緒是不合適的。
  • 當指令碼在 Web Worker 內部執行時,它無法訪問網頁的 window 物件 (window.document)。
  • Web Workers 無法直接訪問網頁和 DOM API。雖然 Web Workers 不會阻塞瀏覽器 UI,但它們仍然會消耗 CPU 週期並使系統響應速度變慢。

Web Workers 的需求

JavaScript 被設計為在單執行緒環境中執行,這意味著多個指令碼無法同時執行。考慮一種情況,您需要處理 UI 事件、查詢和處理大量 API 資料以及操作 DOM。在 CPU 利用率很高的情況下,JavaScript 會導致瀏覽器掛起。

示例

讓我們舉一個簡單的例子,其中 JavaScript 遍歷一個大迴圈。當您執行此程式碼時,您的瀏覽器將變得無響應

<!DOCTYPE html>
<html>
<head>
   <title>Big for loop</title>
   <script>
      function bigLoop() {
         for (var i = 0; i <= 10000000000; i += 1) {
            var j = i;
         }
         alert("Completed " + j + "iterations");
      }
      function sayHello() {
         alert("Hello sir....");
      }
   </script>
</head>

<body>
   <input type="button" 
          onclick="bigLoop();" 
          value="Big Loop" />

   <input type="button" 
          onclick="sayHello();" 
          value="Say Hello" />
</body>
</html>

上面解釋的情況可以使用 Web Workers 來處理,它將在不中斷使用者介面的情況下執行所有計算量大的任務,並且通常在單獨的執行緒上執行。

Web Workers 如何工作?

Web Workers 使用 JavaScript 檔案的 URL 進行初始化,該檔案包含工作執行緒將執行的程式碼。此程式碼設定事件監聽器並與從主頁面生成的指令碼通訊。以下是簡單的語法

var worker = new Worker('bigLoop.js');

如果指定的 JavaScript 檔案存在,瀏覽器將生成一個新的工作執行緒,該執行緒將非同步下載。如果我們工作執行緒的路徑返回 404 錯誤,則工作執行緒將靜默失敗。

如果我們的應用程式有多個支援的 JavaScript 檔案,我們可以使用 importScripts() 方法匯入它們,該方法以逗號分隔的檔名作為引數,如下所示

importScripts("helper.js", "anotherHelper.js");

一旦 Web Worker 生成,Web Worker 和其父頁面之間的通訊就透過 postMessage() 方法完成。根據瀏覽器/版本,postMessage() 方法可以接受字串或 JSON 物件作為其唯一的引數。

Web Worker 傳遞的訊息使用主頁面中的 onmessage 事件進行訪問。以下是將生成 Web Worker 來執行迴圈並返回變數 j 的最終值的主頁面 (hello.htm)

示例

<!DOCTYPE html>
<html>
<head>
   <title>Big for loop</title>
   <script>
      var worker = new Worker('bigLoop.js');
      worker.onmessage = function(event) {
         alert("Completed " + event.data + "iterations");
      };
      function sayHello() {
         alert("Hello sir....");
      }
   </script>
</head>

<body>
   <input type="button" 
          onclick="sayHello();" 
          value="Say Hello" />
</body>
</html>

以下是 bigLoop.js 檔案的內容。它使用 postMessage() API 將通訊傳回主頁面

for (var i = 0; i <= 1000000000; i += 1){
   var j = i;
}
postMessage(j);

bigLoop.js 中的 j 變數使用函式 `postMessage()` 釋出,然後在 hello.htm 中使用 `worker.onmessage = function(event) {}` 的事件屬性接收。

停止 Web Workers

Web Workers 不會自行停止,但啟動它們的頁面可以透過呼叫 terminate() 方法來停止它們。

worker.terminate();

終止的 Web Worker 將不再響應訊息或執行任何其他計算。我們無法重新啟動工作執行緒;相反,我們需要使用相同的 URL 建立一個新的工作執行緒。

處理 Web Workers 錯誤

您可以使用 worker.onerror() 方法從主執行緒處理 Web Worker 中發生的錯誤。

示例

以下顯示了 Web Worker JavaScript 檔案中錯誤處理函式的示例,該函式將錯誤記錄到控制檯。使用錯誤處理程式碼,上面的示例將變為如下所示

<!DOCTYPE html>
<html>
<head>
   <title>Big for loop</title>
   <script>
      var worker = new Worker('bigLoop.js');
      worker.onmessage = function(event) {
         alert("Completed " + event.data + "iterations");
      };
      worker.onerror = function(event) {
         console.log(event.message, event);
      };
      function sayHello() {
         alert("Hello sir....");
      }
   </script>
</head>

<body>
   <input type="button" 
          onclick="sayHello();" 
          value="Say Hello" />
</body>
</html>

您可以使用以下程式碼片段作為主頁面上工作執行緒的錯誤處理程式

worker.onerror = function(event) {
   console.error("Error in web worker: " + event.message, event);
   alert("Error occurred in the web worker.");
   // Prevents the default handling of the error
   event.preventDefault(); 
};

檢查瀏覽器支援

要檢查瀏覽器對 Web Workers 的支援,您可以使用 Modernizr 的 webworkers 功能測試。

示例

以下是檢測瀏覽器中可用的 Web Worker 功能支援的語法

<!DOCTYPE html>
<html>
<head>
   <title>Big for loop</title>
   <script src="/js/modernizr-1.5.min.js">
   </script>

   <script>
      if (Modernizr.webworkers) {
         alert("You have web workers support.");
      } else {
         alert("You do not have web workers support.");
      }
   </script>
</head>

<body>
   <p>
      Checking for Browser Support for web workers
   </p>
</body>
</html>
廣告