HTML Web Workers API

Web Worker 是一个在后台运行的外部 JavaScript 文件,不会影响页面的性能。

什么是 Web Worker?

在 HTML 页面中执行脚本时,页面会变得无响应,直到脚本执行完毕。

Web Worker 是一个在后台运行的外部 JavaScript 文件,独立于其他脚本,不会影响页面的性能。您可以在 Web Worker 在后台运行的同时继续执行任何操作:点击、选择内容等。

Web Worker 对于无法在主线程上运行的重型代码非常有用,避免造成页面无响应的长时间任务。

浏览器支持

表格中的数字指定了完全支持 Web Workers API 的第一个浏览器版本。

Chrome Edge Firefox Safari Opera
Chrome Edge Firefox Safari Opera
4.0 10.0 3.5 4.0 11.5

Web Workers API Example

下面的例子创建了一个在后台计数的简单 Web Worker:

实例

计数数字:

亲自试一试

注意:通常 Web Worker 不用于如此简单的脚本,而是用于更消耗 CPU 的任务!

检查 Web Worker API 支持

在使用 Web Worker 之前,我们可以快速检查浏览器支持:

实例

测试浏览器支持:

<script>
const x = document.getElementById("result");
if(typeof(Worker) !== "undefined") {
  x.innerHTML = "您的浏览器支持 Web Workers!";
} else {
  x.innerHTML = "抱歉,您的浏览器不支持 Web Workers。";
}
</script>

亲自试一试

创建 .js Web Worker 文件

现在,让我们在外部 JavaScript 文件中创建一个 Web Worker。

这里我们创建一个计数脚本。该脚本存储在 "demo_workers.js" 文件中:

var i = 0;

function timedCount() {
  i = i + 1;
  postMessage(i);
  setTimeout("timedCount()",500);
}

timedCount();

注意:上面代码的重要部分是 postMessage() 方法 - 用于将消息发送回 HTML 页面。

创建 Web Worker 对象

创建 .js Web Worker 文件后,我们可以从 HTML 页面调用它。

以下代码检查是否已存在 Worker(w),如果不存在,则创建一个新的 Web Worker 对象并指向 .js 文件:"demo_workers.js":

if (typeof(w) == "undefined") {
  w = new Worker("demo_workers.js");
}

然后,我们可以与 Web Worker 发送和接收消息。

数据通过消息系统在 Web Worker 和主线程之间传递——双方都使用 postMessage() 方法发送消息,并通过 onmessage 事件处理程序响应消息。

向 Web Worker 对象添加一个 onmessage 事件监听器。

w.onmessage = function(event){
  document.getElementById("result").innerHTML = event.data;
};

当 .js 中的 Web Worker 发布消息时,事件监听器内的代码被执行。来自 Web Worker 的数据存储在 event.data 中。

终止 Web Worker

创建 Web Worker 对象后,它将持续监听消息,直到被终止。

要终止 Web Worker 对象并释放浏览器/计算机资源,请使用 terminate() 方法:

w.terminate();

重用 Web Worker

如果在 Web Worker 被终止后将 Web Worker 变量设置为 undefined,则可以重用该 Worker/代码:

w = undefined;

完整的 Web Worker 示例

我们已经在 .js 文件中看到了 Web Worker 代码。

以下是 HTML 页面的完整代码:

实例

<!DOCTYPE html>
<html>
<body>

<p>计数数字:<output id="result"></output></p>
<button onclick="startWorker()">启动 Worker</button>
<button onclick="stopWorker()">停止 Worker</button>

<script>
let w;

function startWorker() {
  const x = document.getElementById("result");
  if (typeof(Worker) !== "undefined") {
    if (typeof(w) == "undefined") {
      w = new Worker("demo_workers.js");
    }
    w.onmessage = function(event) {
      x.innerHTML = event.data;
    };
  } else {
    x.innerHTML = "抱歉!不支持 Web Worker。";
  }
}

function stopWorker() {
  w.terminate();
  w = undefined;
}
</script>

</body>
</html>

亲自试一试

Web Workers 和 DOM

由于 Web Worker 位于外部的 .js 文件中,它们无法访问以下 JavaScript 对象:

  • window 对象
  • document 对象
  • parent 对象