当前位置: 首页 > news >正文

Web Worker 入门指南

在浏览器环境中,JavaScript 是单线程运行的,这意味着当执行一些耗时的操作时(例如大量计算、数据处理等),会阻塞主线程,导致用户界面卡顿,影响用户体验。为了解决这个问题,Web Worker 提供了一种在后台线程中运行脚本的方法,从而避免阻塞主线程。

1. 什么是 Web Worker

Worker 是一个使用构造函数创建的对象(例如 Worker()),它运行一个具名 JavaScript 文件,该文件包含将在 Worker 线程中运行的代码。Worker 运行在另一个全局上下文中,不同于当前的 window。在 Worker 内通过 self 获取全局作用域,而不是 window。

2. Web Worker 的基本用法

2.1 创建 Worker 线程

要创建一个 Worker,需要使用 Worker 构造函数,并传入一个 JavaScript 文件的路径作为参数。例如,假设我们有一个名为 worker.js 的文件:

// worker.js
self.onmessage = (event) => {console.log('worker event: ', event)
};
// 主线程
const worker = new Worker('worker.js');

注:这里的 worker.js 必须与主线程在同一域名下。如果使用构建工具,还需要注意打包后的路径问题

2.2 主线程发送消息给 Worker 线程

要向 Worker 线程发送消息,需要调用 worker.postMessage() 方法,并传入一个要发送的数据作为参数。例如:

// 主线程
const worker = new Worker('worker.js');
worker.postMessage({ num: 10 });

运行后我们可以看到 Worker 线程中接收到的 event.data 属性就是在主线程中传入的值
img

2.3 接收 Worker 线程的消息

在 Worker 线程中,我们可以使用 self.postMessage() 方法向主线程发送消息。主线程可以通过监听 worker.onmessage 事件来接收这些消息。例如:

// worker.js
self.onmessage = (event) => {console.log('worker event: ', event)const { num } = event.data;const result = num + 1;self.postMessage({ value: result });
};
// 主线程
const worker = new Worker('worker.js');
worker.postMessage({ num: 10 });worker.onmessage = (event) => {console.log('main event: ', event);
};

运行后我们可以看到主线程中接收到了 Worker 线程发送的消息,其中 event.data 属性就是 Worker 线程中计算后的结果
img

这样我们就可以把主线程中的耗时操作放到 Worker 线程中执行,等待 Worker 线程执行完成后将结果返回给主线程,从而避免阻塞主线程,提升用户体验

2.4 关闭 Worker 线程

当 Worker 线程不再需要时,应该调用 worker.terminate() 方法来关闭它。这将释放 Worker 线程占用的资源。例如:

// 主线程
const worker = new Worker('worker.js');
worker.postMessage({ num: 10 });worker.onmessage = (event) => {console.log('main event: ', event);worker.terminate();
};

通过 Source 面板对比我们可以看到,调用 worker.terminate() 后 Worker 线程被销毁
img

3. 嵌入式 Worker 线程

有时候我们可能不想单独创建一个 JavaScript 文件来作为 Worker 线程的脚本,这时可以使用 Blob 对象来创建一个内联的 Worker 线程。例如:

const workerScript = `self.onmessage = (event) => {console.log('worker event: ', event)const { num } = event.data;const result = num + 1;self.postMessage({ value: result });};
`;const workerBlob = new Blob([workerScript], { type: 'text/javascript' });
const workerUrl = URL.createObjectURL(workerBlob);
const worker = new Worker(workerUrl);worker.postMessage({ num: 10 });worker.onmessage = (event) => {console.log('main event: ', event);
};

运行后同样可以看到 Worker 线程接收到了主线程的消息,主线程也接收到了 Worker 线程处理后的结果
img

4. 调试 Worker 线程

在浏览器的开发者工具中,可以通过 Source 面板查看和调试 Worker 线程。Worker 线程会显示在 Sources 面板的 Workers 部分,可以像调试主线程一样设置断点、查看变量等

  • 如果使用单独的 JavaScript 文件作为 Worker 线程的脚本,我们可以在 Source 面板通过文件名找到对应的 Worker 文件
    img

  • 如果使用内联的 Worker 线程脚本,Source 面板会有一个随机字符串作为 Worker 文件名,且每次重新加载文件名都会发生变化
    img

5. React 中使用 Worker 线程

import { useCreation } from 'ahooks';
import { Button } from 'antd';
import { useState } from 'react';const workerScript = `self.onmessage = (event) => {const { num } = event.data;const result = num + 1;self.postMessage({ value: result });};
`;export default function WebWorkerPage() {const [num, setNum] = useState(0);const worker = useCreation(() => {const workerBlob = new Blob([workerScript], { type: 'text/javascript' });const workerUrl = URL.createObjectURL(workerBlob);const worker = new Worker(workerUrl);worker.onmessage = (event) => {console.log('main event: ', event.data);setNum(event.data.value);};return worker;}, []);return (<div className="WebWorkerPage"><h4>{num}</h4><Button onClick={() => worker.postMessage({ num })}>Add</Button></div>);
}

示例中使用嵌入式 Worker 线程的方式,并通过 useCreation hook 来创建 Worker 线程,确保只创建一次 Worker 线程实例
点击 Add 按钮后,会向 Worker 线程发送主线程的 num 值,Worker 线程计算 num + 1(可替换为其他阻塞主线程的耗时操作),并将结果返回给主线程,主线程更新 num 的值并显示在页面上
img

参考文档:使用 Web Worker

http://www.zskr.cn/news/46714.html

相关文章:

  • 【JVS更新日志】开源框架升级vue 3、低代码、企业计划、智能BI及其他产品迎来新版本! - 实践
  • 银川西林瓶灌装旋盖机推荐2025,运行稳定连续8小时无故障
  • pg_hba.conf配置里peer,indent和md5的区别
  • 基于Simulink的双电机PID控制仿真实现方案
  • Linux内核架构浅谈26-Linux实时进程调度:优先级反转与解决实用的方案
  • React-router v7 配置 Suspense+lazy fallback第二次不显示
  • 2025年11月高温老化房及环境试验设备推荐厂家:步入式恒温试验室/步入式高低温湿热试验室/大型高低温湿热试验室/汽车零部件、逆变器、电子元器件等场景适用
  • Windows 电脑 FTP 服务器配置
  • 2025抗老面霜爆款推荐:功效全面升级,从 “成分堆砌” 到 “体系抗老”
  • 国标GB28181算法算力平台EasyGBS:构建智慧鱼塘养殖远程监控与智能预警一体化方案
  • 2025年环境试验设备最新推荐厂家,高温老化房、高低温湿热试验室、步入式试验室、汽车零部件老化房
  • React系列教程:10. Button组件示例
  • 阿里云 Maven 仓库
  • 2025年11月油烟机品牌对比:海信领衔五强排行全评价
  • 【251111】CF2161 Div.1+2 vp 总结
  • 2025年11月深圳近视手术医生评测榜:五位口碑医师排行解析
  • 2025年纸板桶生产厂家权威推荐榜单:方纸桶/生产纸板/全纸桶源头厂家精选
  • Request
  • 30段极简Python代码:这些小技巧你都Get了么
  • 2025年电玩摩托定制厂家权威推荐榜单:电玩摩托游戏机/投币式电玩摩托游戏机/电玩城成人摩托源头厂家精选
  • 关键字 字面量 变量
  • “CMTI测试电源”共模瞬态抗扰度测试方案及标准 - FORCREAT
  • C# 操作 Excel
  • 智能字幕校准系统实战(二):6级匹配算法从精确到模糊的全链路解析
  • 基于MATLAB实现支持向量机(SVM)分类
  • 为什么要使用immer库?
  • 游戏AI行为决策——MLP(多层感知机/人工神经网络)
  • 利用合成孔径雷达进行的距离多普勒成像算法
  • 2025最新美国留学机构推荐:资质认证机构清单+ 个性化规划
  • C# DXF文件解析与交互式显示含缩放/拖拽