Web Worker使用指南 解锁浏览器多线程 ,提升前端性能的利器

文章目录

  • 前言
  • 一、什么是 Web Worker
  • 二、适用场景
    • 1、CPU 密集型计算
    • 2、图像/视频处理
    • 3、实时数据流处理(高频场景)
    • 4、后台文件操作
    • 5、复杂状态机/AI逻辑(游戏开发)
    • 6、长轮询与心跳检测
    • 7、WebAssembly 加速
    • 8、WebGL 与 Canvas 渲染
    • 总结
  • 三、Web Worker API详解
    • 快速上手示例:
    • 关键API详解
      • 3.1、主线程中使用:
        • (1)创建实例
        • (2)事件监听
        • (3)实例方法
          • 示例:
      • 3.2、子线程中使用:
        • (1)事件监听
        • (2)向主线程发送消息
        • (3)终止Worker
        • (4)导入外部脚本
    • 总结
      • 1、创建和使用 Worker
      • 2、消息传递机制
      • 3、Worker 线程的限制
    • 注意事项
  • 四、访问浏览器 API
    • Worker无法访问的浏览器 API
      • 1. DOM 操作相关
      • 2. 窗口与视图相关
      • 3. 渲染与动画相关
      • 4、部分全局对象
    • Worker 可使用的API
      • 1、数据存储
      • 2. 网络请求
      • 3. 定时器
      • 4. 多线程协作
  • 五、构建工具中使用Worker
    • 1、Vite
      • 方法1:(添加?worker后缀)
      • 方法2:(new URL)
    • 2、Webpack 5
    • 3、Webpack 4
  • 总结


前言

在现代Web开发中,随着应用复杂度的增加,主线程(UI线程)的负担越来越重。JavaScript的单线程特性意味着耗时任务会阻塞用户交互,导致界面卡顿。Web Worker 的出现为我们提供了一种解决方案,它允许在主线程之外创建后台线程,从而让我们能够并行处理任务,提升应用的响应性和流畅性。本文将深入解析Web Worker的使用技巧,包括在Vite等现代工程化环境中的实践。

请添加图片描述


一、什么是 Web Worker

Web Worker 是 HTML5 规范中引入的一项功能,它允许在浏览器中创建独立于主线程的 JavaScript 线程。这些线程可以在后台运行,执行复杂的计算或 I/O 操作,而不会阻塞主线程的执行。这样,即使在处理大量数据或执行复杂计算时,页面仍然能够保持流畅的交互体验。

Web Worker 的主要特点包括:

  • 独立于主线程的 JavaScript 线程(子线程),不阻塞UI渲染
  • 独立上下文:Worker 拥有自己的全局对象self,非window
  • 通过消息机制与主线程通信
  • 无法直接操作DOM
  • 无法访问document、window、localStorage/sessionStorage等浏览器 API
  • 可以访问部分浏览器 API(如 XMLHttpRequest、localStorage 等)
  • 同源限制:Worker 脚本必须与主线程同源
  • 支持现代ES6+语法

二、适用场景

1、CPU 密集型计算

执行大量计算(如数学运算、数据排序、加密解密)时,主线程会被阻塞导致页面卡顿。例如:

  • 处理 100 万条以上的金融交易数据
  • 处理上万条的表格数据排序
  • 处理上万条的echart数据格式
  • 模拟物理系统或执行复杂算法

2、图像/视频处理

像素级图像滤镜应用(如模糊、锐化)、视频编解码

3、实时数据流处理(高频场景)

物联网传感器流、实时日志分析、WebSocket消息处理

4、后台文件操作

Excel/CSV文件解析,文件上传

5、复杂状态机/AI逻辑(游戏开发)

NPC行为决策树、物理引擎模拟、战斗伤害计算

6、长轮询与心跳检测

定期执行网络请求或状态检查,避免阻塞 UI。在线状态检测、定时数据同步、任务进度监控等

7、WebAssembly 加速

结合 WebAssembly 在 Worker 中执行高性能计算。例如:利用 WebAssembly 加速视频处理、运行轻量级神经网络模型

8、WebGL 与 Canvas 渲染

使用 OffscreenCanvas 将渲染任务转移到 Worker。例如:复杂图形绘制、3D 场景渲染等

总结

Web Worker 的核心价值在于将计算密集型、耗时操作与UI 渲染分离,提升应用响应性,通过结合 Transferable Objects、OffscreenCanvas 和 WebAssembly 等技术,Web Worker 能进一步释放浏览器的多核性能,为用户提供流畅的交互体验。


三、Web Worker API详解

快速上手示例:

计算1+2+3+4+…+1000000000的结果

main.js(主线程)

// main.js (主线程)const worker = new Worker('./worker.js');// 发送消息给Worker
worker.postMessage('start');// 接收Worker的消息
worker.onmessage = event=> {console.log('计算结果为:'+ event.data);
};// 错误处理
worker.onerror =error=> {console.error('error:', error.message);
};

worker.js (Worker线程)

//worker.js (子线程)//接收主线程消息
self.onmessage = event=> {if (event.data === 'start') {// 执行复杂计算let result = 0;for (let i = 0; i < 1000000000; i++) {result += i;}// 发送结果给主线程self.postMessage(result);}
};

Web Worker 创建的线程是独立于主线程的,它有自己的执行上下文和事件循环。Worker 线程无法直接访问 DOM 或主线程的全局变量,但可以通过消息传递机制与主线程通信


关键API详解

3.1、主线程中使用:

(1)创建实例
const worker = new Worker(scriptURL, [options]);
  • scriptURL :指定 Worker 线程执行的 JavaScript 文件的 URL(必须)

    要求:
    (1)必须是同源的 URL(与主页面相同的协议、域名和端口)
    (2)可以是相对路径或绝对路径
    (3)支持数据 URL(Data URL)和 Blob URL

    示例:

// 相对路径
const worker = new Worker('../worker.js');// 绝对路径
const worker = new Worker('/public/worker.js');// 完整 URL
const worker = new Worker('https://example.com/worker.js');// Blob URL(用于内联 Worker)
const blob = new Blob(['self.onmessage = e => self.postMessage(e.data);'], {type: 'application/javascript'});
const worker = new Worker(URL.createObjectURL(blob));
  • options:可选配置对象

    可选属性:

属性名说明类型默认值可选值
type指定 Worker 的类型Stringclassicclassic (传统脚本类型)、module:(ES6 模块类型,支持 import语法,构建工具内开发常配置)
credentials模块脚本的凭证(仅当 type: ‘module’ 时有效)Stringsame-originomit(不带凭证)、same-origin(同源带凭证)、include(跨域带凭证)
nameWorker 实例标识名(可通过 self.name 在 Worker 内部访问)String————

示例:

//子线程使用 ES6 模块类型
const worker = new Worker('worker-module.js', { type: 'module' });
// worker-module.js (ES6 模块)
import { helperFunction } from './utils.js';self.onmessage = event => {const result = helperFunction(event.data);self.postMessage(result);
};

创建成功后返回一个 Worker 对象实例

(2)事件监听
  • onmessage:消息事件处理函数,监听来自子线程消息,回调通过event.data获取数据
  • onerror:错误事件处理函数

上述事件也可以使用addEventListener方法代替:

// main.js
const worker = new Worker('worker.js');
//监听子线程消息
worker.onmessage = event=> {console.log('来自子线程消息', event.data);
};
//或写成如下
worker.addEventListener('message', e => {console.log(e.data,'来自子线程消息');
});//错误事件处理
worker.onerror = e=> {console.log(e,'执行错误');
};
//或写成如下
worker.addEventListener('error',e=>{console.log(e,'执行错误');
})
(3)实例方法
  • postMessage(message, [transfer]): 向 Worker(子线程)发送消息
  • terminate: 立即终止 Worker 线程
  • addEventListener:事件监听方法
示例:

1、主线程向子线程发送消息

// 主线程发送消息
worker.postMessage({ type: 'CALC_FIB', value: 40 });

2、终止Worker

// 主线程中终止
worker.terminate();

3.2、子线程中使用:

注意子线程中,全局对象为self,非window

(1)事件监听

跟主线程一样通过onmessage 监听来自主线程消息,回调通过event.data获取数据

// worker.js 
//消息事件处理函数
self.onmessage = event => {console.log('接收来自主线程消息', event.data);};
(2)向主线程发送消息

跟主线程一样通过postMessage给主线程发送消息

self.postMessage('来自子线程消息');
(3)终止Worker
// Worker内部自终止
self.close();
(4)导入外部脚本

在 Worker 内部可以使用importScripts()方法导入外部脚本:

importScripts('script1.js', 'script2.js');

总结

1、创建和使用 Worker

创建 Worker 需要一个独立的 JavaScript 文件,主线程通过 Worker() 构造函数初始化这个 Worker

2、消息传递机制

主线程和 Worker 之间通过 postMessage() 方法发送消息,并通过 onmessage 事件监听消息。消息可以是基本数据类型、对象或数组。如果是引用类型,数据会被序列化和反序列化,在两端创建独立的副本(深拷贝)。

3、Worker 线程的限制

无法直接访问以下主线程资源:DOM 元素、window、document、parent 等对象


注意事项

1、同源限制:Worker 脚本必须与主页面同源,否则会抛出安全错误
2、路径问题:Worker 脚本中的相对路径是相对于脚本本身,而非主页面
3、调试技巧:使用 name 选项为 Worker 命名,便于在浏览器开发者工具中识别,Worker 线程的控制台输出会显示 在浏览器的调试工具中
4、生命周期:Worker 线程会一直运行,直到被显式终止(worker.terminate() 或 self.close())
5、模块支持:使用 type: ‘module’ 时,需要确保浏览器支持 ES6 模块
6、资源消耗:创建过多的 Worker 会消耗大量系统资源,应合理控制 Worker 的数量


四、访问浏览器 API

上面章节多次提到了 Worke不能轻易访问浏览器 API,特别是涉及UI操作API几乎受到限制,对此本小节我们将做一个全面总结归纳哪些api受限制哪些可使用。

Worker无法访问的浏览器 API

1. DOM 操作相关

  • document对象:无法直接操作 HTML 文档树
  • window对象:缺少所有与窗口相关的属性和方法
  • document.querySelector():无法选择或修改 DOM 元素
  • CSSOM:无法访问或修改 CSS 样式

2. 窗口与视图相关

  • window.innerWidth/innerHeight:无法获取窗口尺寸
  • scrollTo():无法控制页面滚动
  • alert()/confirm():无法显示模态对话框
  • localStorage/sessionStorage:无法直接访问存储 API(但可通过IndexedDB操作)

3. 渲染与动画相关

  • requestAnimationFrame():无法参与主线程渲染循环
  • Canvas 2D 上下文:无法直接绘制(但可通过OffscreenCanvas间接使用)
  • WebGL:无法直接使用(需通过OffscreenCanvas)

4、部分全局对象

  • location对象:仅能访问有限属性(如location.origin)
  • history对象:无法操作浏览器历史记录

Worker 可使用的API

1、数据存储

  • IndexedDB:支持异步数据库操作
  • File API:可读写文件系统(需用户交互授权)

2. 网络请求

  • Fetch API:支持异步网络请求
  • XMLHttpRequest:与主线程用法一致

3. 定时器

  • setTimeout()/setInterval():基本定时器功能正常使用

4. 多线程协作

  • postMessage():线程间通信核心 API
  • SharedArrayBuffer:支持多线程共享内存

五、构建工具中使用Worker

本章节将讲述 Vite、Webpack 4 和 Webpack 5 中 Web Worker 的使用差异及最佳实践

1、Vite

Vite 从 2.6.0 版本开始内置了对 Web Worker 的支持,无需额外插件即可直接使用,这得益于 ES Module 的动态导入特性

方法1:(添加?worker后缀)

//main.js 主线程
import CalcWorker from './calcWorker.js?worker'; // 关键后缀语法
const worker = new CalcWorker();
worker.postMessage({ data:10 });
worker.onmessage = (e) => {console.log('Result:', e.data);
};
//worker.js子线程
import {heavyCalculation} from '../utils/calculation.js'
self.onmessage = (e) => {const result = heavyCalculation(e.data);postMessage(result);};

说明:导入worker文件路径添加“ ?worker“ 后缀触发特殊处理,将 worker 文件编译为独立 [name].worker.js 的 chunk,自动生成 new Worker(new URL(‘./calcWorker.worker.js’, import.meta.url)) 的现代化语法,开发环境下使用浏览器原生 ESM 加载,生产构建为独立文件。

方法2:(new URL)

//main.js 主线程
const worker = new Worker(new URL("./calcWorker.js", import.meta.url), {type: "module",//启用模块化
});
//calcWorker.js子线程
import {heavyCalculation} from '../utils/calculation.js'
self.onmessage = (e) => {const result = heavyCalculation(e.data);postMessage(result);};

说明:自动将 worker 拆分为独立 chunk,支持 SourceMap,如果worker中使用import导入其他模块文件,构造函数必须设置type: “module”,开启对ESM支持

2、Webpack 5

Webpack5 不再需要额外的 loader,通过 new Worker() 即可直接使用,底层依赖于 worker-plugin 的内置支持。

使用方法同vite方法2

//main.js 主线程
const worker = new Worker(new URL('./dataWorker.js', import.meta.url));worker.onmessage = (event) => {console.log('处理结果:', event.data);// 更新UI
};// 发送数据给Worker
worker.postMessage({data: [{ id: 1, value: 5 },{ id: 2, value: 15 },{ id: 3, value: 20 },// 更多数据...]
});
//dataWorker.js子线程
// 模拟大数据处理
self.onmessage = (event) => {const { data } = event.data;// 复杂数据过滤const filteredData = data.filter(item => item.value > 10);self.postMessage(filteredData);
};

说明:Webpack 5内置支持 new Worker() + import.meta.url 规范,自动将 worker 拆分为独立 chunk,支持 SourceMap,热更新需要手动配置可通过 experiments.worker: true 开启

3、Webpack 4

Webpack4 需要借助 worker-loader 来处理 Worker 脚本,该 loader 会将 Worker 脚本打包为可独立执行的模块。

(1)安装依赖

npm install worker-loader --save-dev

(2)配置 webpack.config.js

module.exports = {// 其他配置...module: {rules: [{test: /\.worker\.js$/,use: {loader: 'worker-loader',options: {// 配置 Worker 输出路径name: 'workers/[name]-[hash].js'}}}]}
};

(3)页面使用
方法同Vite 方法1

//main.js 主线程
import MyWorker from '../worker/heavyTask.worker.js';const worker = new MyWorker();// 开始计时
const startTime = Date.now();
worker.postMessage({ startTime });worker.onmessage = (event) => {console.log('计算结果:', event.data.result);console.log(`耗时: ${event.data.duration}ms`);// 更新界面显示结果
};
//heavyTask.worker.js子线程
self.onmessage = (event) => {// 模拟 CPU 密集型任务let sum = 0;for (let i = 0; i < 100000000; i++) {sum += i;}self.postMessage({ result: sum, duration: Date.now() - event.data.startTime });
};

说明:Webpack4 中建议使用 .worker.js 后缀以便 loader 识别,缺少原生 HMR 支持,修改 worker 需手动刷新


总结

Web Worker 为前端开发者打开了并行计算的大门,通过合理使用可以显著提升应用性能和用户体验。掌握其核心原理、应用模式和性能优化技巧,将使你在构建现代 Web 应用时如虎添翼。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86371.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86371.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React 18.2.0 源码打包

一、React源码地址 GitHub&#xff1a;React 二、参考文章 sourcemap实战-生成react源码sourcemap Rollup中文文档 JavaScript Source Map 详解 全网最优雅的 React 源码调试方式 三、打包操作 安装依赖 // 全局安装yarn npm i -g yarn // 源码项目目录下执行yarn安装依赖…

UniApp 开发第一个项目

UniApp 开发第一个项目全流程指南,涵盖环境搭建、项目创建、核心开发到调试发布,结合最新实践整理而成,适合零基础快速上手: 🧰 一、环境准备(5分钟) 安装开发工具 HBuilderX(官方推荐IDE):下载 App 开发版,安装路径避免中文或空格 微信开发者工具(调试小程序必备…

Web项目开发中Tomcat10+所需的jar包

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 项目背景 Web项目中使用低版本Tomcat时常用的jar包如下&#xff1a; javax.servlet-apijavax.ejb-apijavax.jms-apijavax.json-api 当Web项目使用Tomcat10的版本时&#…

网络安全就业方向与现实发展分析:机遇、挑战与未来趋势

网络安全行业的战略地位与就业背景 在数字经济蓬勃发展的今天&#xff0c;网络安全已从技术分支演变为关乎国家安全、企业存亡和个人隐私的核心领域。根据国家网信办数据显示&#xff0c;2025年我国网络安全人才缺口达200万人&#xff0c;较2023年增长33%。这一现象源于三重驱…

iOS runtime随笔-消息转发机制

运行时的消息转发分三步, 当你调用了没有实现的方法时, 有机会通过runtime的消息转发机制补救一下 resolveInstanceMethod/resolveClassMethod 这里可以动态去创建方法来解决CrashforwardingTargetForSelector ​​​​​第一步未解决, 就会走到这里, 可以给出一个Target去转发…

vue3用js+css实现轮播图(可调整堆叠程度)

先看效果 html <divclass"outer"style"width: 650px;background: #fff;box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);border-radius: 15px;margin: 0 10px 15px 5px;">//这里用的是svg-icon,需要的可自行替换为其他图片<svg-iconid"btn_l&q…

Three.js项目实战:从零搭建小米SU7三维汽车

大家如果有过购车的经验&#xff0c;肯定会先从网站上收集车辆的信息&#xff0c;比如懂车帝&#xff0c;汽车之家&#xff0c;这些网站上逼真的看车效果是如何实现的呢&#xff0c;这节课带你从0-1快速的手搓一个看车小项目。 懂车帝官网 效果 视频教程和笔记 大家可以下方小…

Android13 永久关闭SELinux 权限

永久关闭 SeLinux 在cmdline中增加参数androidboot.selinuxpermissive&#xff1b; 芯片: QCM6115 版本: Android 13 kernel: msm-4.19 ~/temp_code/SLM927D_LA.UM.9.15$ git diff device/qcom/bengal/BoardConfig.mk diff --git a/device/qcom/bengal/BoardConfig.mk b…

Linux创建DHCP服务

Linux可作为DHCP服务端使用&#xff0c;为同一个网络下的其它机器动态分配ip。在一些情况下&#xff0c;可以起到很大的作用。 二级标题 安装dnsmasq # ubuntu sudo apt update -y sudo apt install -y dnsmasq# centos sudo yum install -y dnsmasq修改配置文件 sudo vim …

汽车4G-TBOX智能终端 汽车国标GB/T 32960协议

汽车国标GB/T 32960协议4G TBOX是一种广泛应用于车联网的设备&#xff0c;下面将从不同方面为你详细介绍。 移动管家汽车4G-TBOX智能终端定义与用途 4G TBOX是基于车联网技术智能服务系统中的采集终端。以车云网的4G TBOX_CC750为例&#xff0c;它为整个智能服务系统提供GPS/…

JavaEE-Mybatis初阶

什么是MyBatis MyBatis是⼀款优秀的 持久层 框架&#xff0c;⽤于简化JDBC的开发。 MyBatis本是 Apache的⼀个开源项⽬iBatis&#xff0c;2010年这个项⽬由apache迁移到了google code&#xff0c;并 且改名为MyBatis 。2013年11⽉迁移到Github 创建项目时添加依赖 上面有…

记一次jvm机器问题定位经历

背景 开发过程中发现机器指标异常&#xff0c;端口也hang住无响应&#xff0c;端口返回为timeout&#xff0c;对应探活检测也失败了。 现象 在st测试环节&#xff0c;突然每隔一段时间新接口就hang住无响应&#xff0c;观察机器监控也发现端口探活失败&#xff0c;看机器指标…

【机器学习深度学习】张量基本操作

目录 一、张量基本操作 1.1 执行代码 1.2 运行结果 1.3 代码解析 ✅ 1. 创建张量&#xff08;tensor、randn、zeros&#xff09; ✅ 2. 索引与切片&#xff08;类似 NumPy&#xff09; ✅ 3. 形状变换&#xff08;reshape、转置、压缩&#xff09; ✅ 4. 数学运算&#x…

【微信小程序】8、获取用户当前的地理位置

1、获取当前的地理位置 获取当前的地理位置、速度。当用户离开小程序后&#xff0c;此接口无法调用。开启高精度定位&#xff0c;接口耗时会增加&#xff0c;可指定 highAccuracyExpireTime 作为超时时间。 注意&#xff1a; 地图相关使用的坐标格式应为 gcj02。高频率调用会…

Jenkins 常用定时构建脚本

Jenkins 常用定时构建脚本 Jenkins 使用 cron 风格的语法来配置定时构建任务&#xff0c;以下是常用的定时构建脚本示例和说明&#xff1a; 基本语法 Jenkins 定时构建使用五个字段表示时间&#xff0c;格式为&#xff1a; MINUTE HOUR DOM MONTH DOWMINUTE - 分钟 (0-59)H…

ActiveMQ漏洞复现

以下内容均在nextcyber靶场环境中完成&#xff0c;请勿用于非法途径&#xff01; ActiveMQ 反序列化漏洞&#xff08;CVE-2015-5254&#xff09; Apache ActiveMQ是美国阿帕奇&#xff08;Apache&#xff09;软件基金会所研发的一套开源的消息中间件&#xff0c;它支持Java消息…

环保处理设备远程运维管理解决方案

在环保产业蓬勃发展的当下&#xff0c;环保处理设备厂商面临着愈发激烈的市场竞争。为助力环保处理设备厂商在竞争中脱颖而出&#xff0c;御控工业智能网关打造了一套完善的PLC数据采集设备运维管理平台解决方案。此方案凭借其独特优势&#xff0c;能为环保处理设备厂商带来显著…

嵌入式学习笔记DAY43(ARM架构)

一、RAM分类 sram&#xff08;静态随机存取存储器&#xff09;&#xff1a; 原理&#xff1a;使用晶体管来存储二进制数据0和1&#xff0c;通过双稳态电路&#xff08;由多个晶体管组成&#xff09;来保持数据状态&#xff0c;只要持续供电&#xff0c;数据就能稳定保存。数据读…

2025国际无人机应用及防控大会四大技术专题深度解析

2025国际无人机应用及防控大会四大技术专题深度解析 2025国际无人机应用及防控大会四大技术专题深度解析1 无人机系统技术专题技术特点与应用领域国内领军企业及案例风险挑战与发展方向 2 测控与通信导航技术专题技术创新与应用突破领先企业及解决方案现存问题与发展趋势 3 任务…

DD3118S:USB3.0+Type-c双头TF/SD二合一高速0TG多功能手机读卡器ic

DD3118S封装是QFN42, GL3224封装是QFN32 &#xff0c;设计同样一款3.0读卡方案&#xff0c;GL3213S需要电容、电阻外围器件一起要29颗&#xff0c;而DD3118S只需要13颗&#xff0c;方案精简且设计简单 DD3118S支持USB3.0Type-c双头TF/SD二合一 &#xff0c;高速0TG多功能手机读…