Web Workers

79 阅读2分钟

JavaScript Web Workers 是一种在后台运行 JavaScript 代码的方式,与 Web 应用程序的主线程分开执行。这使得脚本可以在不阻塞用户界面的情况下并发执行,特别适用于那些会使页面无响应的计算密集型任务。

关键概念

  1. 主线程 vs 工作线程

    主线程:负责处理DOM和用户交互。

    工作线程:在单独的线程中运行,与主线程隔离,可以执行任务而不影响主线程的性能。

  2. 通讯

    主线程和工作线程之间的通讯通过消息进行。

    使用 postMessage 方法发送数据到工作线程或返回到主线程。

    使用 onmessage 事件处理器接收消息。

  3. 共享工作线程 vs 专用工作线程

    共享工作线程:可以被多个脚本访问的工作线程,这些脚本可以运行在不同的窗口、iframe 甚至其他工作线程中。

    专用工作线程:由单个脚本使用的工作线程。

  4. 工作线程作用域

    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('共享工作线程的消息');
    };
};