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 对象