JavaScript Web Workers 是一种在后台运行 JavaScript 代码的方式,与 Web 应用程序的主线程分开执行。这使得脚本可以在不阻塞用户界面的情况下并发执行,特别适用于那些会使页面无响应的计算密集型任务。
关键概念
-
主线程 vs 工作线程
主线程:负责处理DOM和用户交互。
工作线程:在单独的线程中运行,与主线程隔离,可以执行任务而不影响主线程的性能。
-
通讯
主线程和工作线程之间的通讯通过消息进行。
使用 postMessage 方法发送数据到工作线程或返回到主线程。
使用 onmessage 事件处理器接收消息。
-
共享工作线程 vs 专用工作线程
共享工作线程:可以被多个脚本访问的工作线程,这些脚本可以运行在不同的窗口、iframe 甚至其他工作线程中。
专用工作线程:由单个脚本使用的工作线程。
-
工作线程作用域
Web Workers 运行在与主线程不同的全局作用域中,由 WorkerGlobalScope表示。
self 关键字在工作线程中引用全局作用域。
功能
-
Web Workers 可以执行诸如复杂计算、数据处理甚至网络操作(通过 fetch 或 XMLHttpRequest)等任务。
-
它们可以使用 setTimeout 、setInteval 和 XMLHttpRequest。
限制
-
Web Workers 无法访问DOM
-
它们不能直接与用户界面交互
-
它们对 window 对象及其属性和方法访问有限。
使用场景
-
繁重计算:将复杂的计算任务卸载到 Web Worker,以保持主线程的响应性。
-
数据处理:处理大数据集或执行数据转换而不阻塞UI。
-
后台任务:在后台运行任务,如轮询服务器或处理 WebSocker 链接。
示例
基础示例
主线程(main.js)
// 创建一个新的 Web Worker
const worker = new Worker('worker.js');
// 向工作线程发送消息
worker.postMessage({ operation: 'multiply', values: [2, 3] });
// 监听来自工作线程的消息
worker.onmessage = function(event) {
console.log('来自工作线程的结果:', event.data);
};
工作线程(worker.js)
// 监听来自主线程的消息
self.onmessage = function(event) {
const { operation, values } = event.data;
let result;
if (operation === 'multiply') {
result = values.reduce((acc, val) => acc * val, 1);
}
// 将结果发送回主线程
self.postMessage(result);
};
共享工作线程示例
主线程(main.js)
const worker = new SharedWorker('shared-worker.js');
worker.port.start(); // 启动工作线程
worker.port.postMessage('主线程的消息');
worker.port.onmessage = function(event) {
console.log('来自共享工作线程的消息:', event.data);
};
共享工作线程 (shared-worker.js)
const ports = [];
self.onconnect = function(event) {
const port = event.ports[0];
ports.push(port);
port.onmessage = function(event) {
console.log('接收到的消息:', event.data);
port.postMessage('共享工作线程的消息');
};
};