Html 简明教程

HTML - Web Workers API

HTML Web 工作线程用于在单独的线程中以后台方式运行计算密集型任务,而不会中断用户界面。

HTML Web Workers are used to run computationally expensive tasks in background in a separate thread without interrupting user interface.

What are Web Workers?

  1. Web Workers allows long tasks to be executed without yielding to keep the page unresponsive.

  2. Web Workers are background scripts and they are relatively heavy-weight, and are not intended to be used in large numbers. For example, it would be inappropriate to launch one worker for each pixel of a four-megapixel image.

  3. When a script is executing inside a Web Worker it cannot access the web page’s window object (window.document).

  4. Web Workers don’t have direct access to the web page and the DOM API. Although Web Workers cannot block the browser UI, they can still consume CPU cycles and make the system less responsive.

What is the need of Web Workers?

JavaScript 旨在在单线程环境中运行,这意味着多个脚本无法同时运行。考虑一个示例,在该示例中,你需要处理 UI 事件、查询和处理大量的 API 数据,以及操作 DOM。当 CPU 利用率高时,JavaScript 将挂起你的浏览器。

JavaScript was designed to run in a single-threaded environment, meaning multiple scripts cannot run at the same time. Consider a situation where you need to handle UI events, query and process large amounts of API data, and manipulate the DOM. JavaScript will hang your browser in situation where CPU utilization is high.

让我们举一个简单的示例,其中 JavaScript 经历了一个大循环,当运行此代码时,浏览器将无响应

Let us take a simple example where JavaScript goes through a big loop, Your browser will become unresponsive when you run this code

<!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 来解决,它将在不中断用户界面的情况下完成所有计算密集型任务,并通常在单独的线程上运行。

The situation explained above can be handled using Web Workers which will do all the computationally expensive tasks without interrupting the user interface and typically run on separate threads.

How Web Workers Work?

网络工作者使用一个 JavaScript 文件的 URL 初始化,该文件包含工作者将执行的代码。此代码设置事件侦听器并与从主页面生成它的脚本通信。以下是简单的语法:

Web Workers are initialized with the URL of a JavaScript file, which contains the code the worker will execute. This code sets event listeners and communicates with the script that spawned it from the main page. Following is the simple syntax:

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

如果指定了 JavaScript 文件,则浏览器将生成一个新工作线程,该线程将异步下载。如果我们的工作线程路径返回 404 错误,则工作线程将静默失败。

If the specified JavaScript file exists, the browser will spawn a new worker thread, which is downloaded asynchronously. If the path to our worker returns a 404 error, the worker will fail silently.

如果我们的应用程序具有多个支持性 JavaScript 文件,则我们可以使用 importScripts() 方法导入它们,该方法采用以逗号分隔的文件名为参数,如下所示:

If our application has multiple supporting JavaScript files, we can import them using the importScripts() method which takes file name(s) as argument separated by comma as follows:

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

生成网络工作者后,网络工作者及其父页面之间的通信使用 postMessage() 方法完成。取决于浏览器/版本, postMessage() 方法可接受字符串或 JSON 对象作为其单个参数。

Once the Web Worker is spawned, communication between web worker and its parent page is done using the postMessage() method. Depending on the browser/version, the postMessage() method can accept either a string or JSON object as its single argument.

网络工作者传递的消息在主页面中使用 onmessage 事件进行访问。以下是主页面 (hello.htm),它将生成一个网络工作者以执行循环并返回变量 j 的最终值:

Message passed by Web Worker is accessed using onmessage event in the main page. Below is the main page (hello.htm) which will spawn a web worker to execute the loop and to return the final value of variable j:

<!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 将通信传递回主页面:

Following is the content of bigLoop.js file. This makes use of postMessage() API to pass the communication back to main page:

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

使用函数 postMessage() 发布 bigLoop.js 中的 j 变量,然后使用 worker.onmessage = function(event) {} 的事件属性在 hello.htm 中接收。

The j variable from bigLoop.js is published using function postMessage(), Which then received at hello.htm using event attribute of worker.onmessage = function(event) {}

Stopping Web Workers

网络工作者不会自行停止,但启动它们的页面可以通过调用 terminate() 方法来停止它们。

Web Workers don’t stop by themselves but the page that started them can stop them by calling terminate() method.

worker.terminate();

终止的网络工作者将不再响应消息或执行任何其他计算。我们无法重新启动工作者;相反,我们需要使用相同的 URL 创建一个新的工作者。

A terminated Web Worker will no longer respond to messages or perform any additional computations. We cannot restart a worker; instead, we need to create a new worker using the same URL.

Handling Errors

以下是如何在网络工作者 JavaScript 文件中处理错误的函数,它将错误记录到控制台。有了错误处理代码,上面的示例将变成如下所示:

The following shows an example of an error handling function in a Web Worker JavaScript file that logs errors to the console. With error handling code, above example would become as following:

<!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>

Checking for Browser Support

以下是检测浏览器中可用的网络工作者功能支持的语法:

Following is the syntax to detect a Web Worker feature support available in a browser:

<!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>