HTML5 Web Workers
JavaScript 是单线程的,这意味着它在同一时间只能做一件事。如果一个脚本需要执行一个非常耗时、计算密集的任务(例如,处理大量数据、复杂的数学计算),它会阻塞主线程,导致整个用户界面 (UI) 被冻结,页面无法响应用户的任何操作(如点击、滚动),从而带来极差的用户体验。
Web Workers 就是 HTML5 为解决这个问题而引入的。Web Worker 是一个在后台运行的 JavaScript 脚本,它独立于主线程,不会影响页面的性能和响应。
Web Worker 的特点
- 后台线程: Worker 在一个与主线程分离的后台线程中运行。
- 无 UI 阻塞: 你可以将耗时的计算任务交给 Worker,而主线程可以继续自由地处理用户交互和 DOM 更新。
- 受限的访问: 出于线程安全的考虑,Worker 无法直接访问主线程的
window对象、document对象和父页面的 DOM 节点。 - 通信机制: Worker 通过消息传递机制与主线程进行通信。
如何使用 Web Worker
使用 Web Worker 分为三个主要步骤:创建 Worker、在主线程和 Worker 之间收发消息、终止 Worker。
1. 创建 Worker 文件
首先,你需要创建一个独立的 .js 文件,这里我们称之为 demo_worker.js。这个文件将包含你希望在后台执行的代码。
demo_worker.js:
javascript
// 一个简单的计数任务
let i = 0;
function timedCount() {
i = i + 1;
// 将当前计数值发送回主线程
postMessage(i);
setTimeout(timedCount, 500);
}
timedCount();postMessage() 是 Worker 向主线程发送消息的方法。
2. 在主页面中创建和控制 Worker
在你的主 HTML 页面中,你可以创建并与 Worker 进行交互。
html
<p>计数: <output id="result"></output></p>
<button onclick="startWorker()">开始 Worker</button>
<button onclick="stopWorker()">停止 Worker</button>
<script>
let w;
function startWorker() {
// 检查浏览器是否支持 Web Worker
if (typeof(Worker) !== "undefined") {
// 如果 w 还未创建,则创建一个新的 Worker
if (typeof(w) == "undefined") {
w = new Worker("demo_worker.js");
}
// 监听来自 Worker 的消息
w.onmessage = function(event) {
document.getElementById("result").innerHTML = event.data;
};
} else {
document.getElementById("result").innerHTML = "抱歉,您的浏览器不支持 Web Workers...";
}
}
function stopWorker() {
// 终止 Worker
if (typeof(w) !== "undefined") {
w.terminate();
w = undefined; // 重置 Worker 变量
}
}
</script>new Worker("demo_worker.js"): 创建一个新的 Web Worker 对象。w.onmessage: 设置一个事件监听器,用于接收 Worker 通过postMessage()发送回来的数据。数据包含在event.data属性中。w.terminate(): 立即终止 Worker 的运行。这是一个从主线程侧停止 Worker 的方法。
这个例子清晰地展示了如何将一个持续运行的计数任务放到后台,而主页面可以自由地响应用户的“开始”和“停止”操作,UI 不会卡顿。