JavaScript系列(39)-- Web Workers技术详解

JavaScript Web Workers技术详解 🔄

今天,让我们深入了解Web Workers技术,这是一种能够在后台线程中运行脚本的强大特性,可以避免阻塞主线程,提升Web应用的性能和响应性。

Web Workers基础概念 🌟

💡 小知识:Web Workers允许在浏览器中运行后台线程,可以执行计算密集型任务而不影响用户界面的响应性。它们通过消息传递机制与主线程通信,不能直接访问DOM。

基本实现 📊

// 1. Worker基础实现
// main.js
class WorkerManager {constructor(workerScript) {this.worker = new Worker(workerScript);this.setupEventListeners();}setupEventListeners() {this.worker.onmessage = (event) => {console.log('Received from worker:', event.data);};this.worker.onerror = (error) => {console.error('Worker error:', error);};}sendMessage(data) {this.worker.postMessage(data);}terminate() {this.worker.terminate();}
}// worker.js
self.onmessage = (event) => {const result = processData(event.data);self.postMessage(result);
};function processData(data) {// 处理数据的逻辑return data.map(x => x * 2);
}// 2. 共享Worker实现
// shared-worker.js
const connections = new Set();self.onconnect = (event) => {const port = event.ports[0];connections.add(port);port.onmessage = (e) => {// 广播消息给所有连接for (const connection of connections) {connection.postMessage(e.data);}};port.start();
};// 3. Worker Pool实现
class WorkerPool {constructor(workerScript, poolSize = 4) {this.workers = [];this.queue = [];this.activeWorkers = new Set();for (let i = 0; i < poolSize; i++) {const worker = new Worker(workerScript);this.setupWorker(worker);this.workers.push(worker);}}setupWorker(worker) {worker.onmessage = (event) => {this.handleTaskCompletion(worker, event.data);};worker.onerror = (error) => {console.error('Worker error:', error);this.handleTaskCompletion(worker, null, error);};}handleTaskCompletion(worker, result, error = null) {const task = this.activeWorkers.get(worker);if (task) {if (error) {task.reject(error);} else {task.resolve(result);}this.activeWorkers.delete(worker);}this.processNextTask(worker);}processNextTask(worker) {if (this.queue.length > 0) {const task = this.queue.shift();this.executeTask(worker, task);}}executeTask(worker, task) {this.activeWorkers.set(worker, task);worker.postMessage(task.data);}async execute(data) {return new Promise((resolve, reject) => {const task = { data, resolve, reject };const availableWorker = this.workers.find(w => !this.activeWorkers.has(w));if (availableWorker) {this.executeTask(availableWorker, task);} else {this.queue.push(task);}});}terminate() {this.workers.forEach(worker => worker.terminate());this.workers = [];this.queue = [];this.activeWorkers.clear();}
}

高级功能实现 🚀

// 1. 可转移对象处理
class TransferableWorkerManager {constructor(workerScript) {this.worker = new Worker(workerScript);}async processArrayBuffer(buffer) {return new Promise((resolve, reject) => {this.worker.onmessage = (event) => {resolve(event.data);};this.worker.onerror = (error) => {reject(error);};// 转移ArrayBuffer所有权this.worker.postMessage({ buffer }, [buffer]);});}async processImageData(imageData) {return new Promise((resolve, reject) => {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');canvas.width = imageData.width;canvas.height = imageData.height;ctx.putImageData(imageData, 0, 0);canvas.toBlob((blob) => {const reader = new FileReader();reader.onload = () => {const buffer = reader.result;this.worker.postMessage({ buffer }, [buffer]);};reader.readAsArrayBuffer(blob);});this.worker.onmessage = (event) => {resolve(new ImageData(new Uint8ClampedArray(event.data.buffer),imageData.width,imageData.height));};});}
}// 2. 错误处理和恢复
class ResilientWorker {constructor(workerScript, options = {}) {this.workerScript = workerScript;this.options = {maxRetries: 3,retryDelay: 1000,...options};this.createWorker();}createWorker() {this.worker = new Worker(this.workerScript);this.setupEventListeners();}setupEventListeners() {this.worker.onerror = (error) => {this.handleError(error);};}async handleError(error) {console.error('Worker error:', error);if (this.options.maxRetries > 0) {this.options.maxRetries--;await new Promise(resolve => setTimeout(resolve, this.options.retryDelay));this.restartWorker();} else {throw new Error('Worker failed after max retries');}}restartWorker() {this.worker.terminate();this.createWorker();}async execute(task) {return new Promise((resolve, reject) => {const timeoutId = setTimeout(() => {reject(new Error('Worker timeout'));this.restartWorker();}, this.options.timeout || 30000);this.worker.onmessage = (event) => {clearTimeout(timeoutId);resolve(event.data);};this.worker.postMessage(task);});}
}// 3. 状态管理
class StatefulWorker {constructor(workerScript) {this.worker = new Worker(workerScript);this.state = new Map();this.setupEventListeners();}setupEventListeners() {this.worker.onmessage = (event) => {const { type, payload } = event.data;switch (type) {case 'STATE_UPDATE':this.updateState(payload);break;case 'STATE_REQUEST':this.sendState();break;default:this.handleMessage(event.data);}};}updateState(changes) {for (const [key, value] of Object.entries(changes)) {this.state.set(key, value);}this.notifyStateChange();}sendState() {const stateObj = {};for (const [key, value] of this.state) {stateObj[key] = value;}this.worker.postMessage({type: 'STATE_SYNC',payload: stateObj});}notifyStateChange() {if (this.onStateChange) {const stateObj = {};for (const [key, value] of this.state) {stateObj[key] = value;}this.onStateChange(stateObj);}}
}

性能优化技巧 ⚡

// 1. 任务分片处理
class TaskChunker {constructor(chunkSize = 1000) {this.chunkSize = chunkSize;}*splitTask(data) {for (let i = 0; i < data.length; i += this.chunkSize) {yield data.slice(i, Math.min(i + this.chunkSize, data.length));}}async processWithWorker(worker, data) {const results = [];for (const chunk of this.splitTask(data)) {const result = await new Promise((resolve, reject) => {worker.onmessage = (e) => resolve(e.data);worker.onerror = (e) => reject(e);worker.postMessage(chunk);});results.push(result);}return results.flat();}
}// 2. Worker缓存优化
class CachedWorker {constructor(workerScript) {this.worker = new Worker(workerScript);this.cache = new Map();this.setupCache();}setupCache() {this.worker.onmessage = (event) => {const { id, result } = event.data;const resolver = this.cache.get(id);if (resolver) {resolver(result);this.cache.delete(id);}};}async execute(task) {const taskId = this.generateTaskId(task);const cachedResult = this.cache.get(taskId);if (cachedResult) {return cachedResult;}return new Promise((resolve) => {this.cache.set(taskId, resolve);this.worker.postMessage({ id: taskId, task });});}generateTaskId(task) {return JSON.stringify(task);}
}// 3. 资源管理优化
class WorkerResourceManager {constructor() {this.resources = new Map();this.maxMemory = 100 * 1024 * 1024; // 100MBthis.currentMemory = 0;}allocate(size) {if (this.currentMemory + size > this.maxMemory) {this.cleanup();}if (this.currentMemory + size > this.maxMemory) {throw new Error('Insufficient memory');}const buffer = new ArrayBuffer(size);this.resources.set(buffer, size);this.currentMemory += size;return buffer;}release(buffer) {const size = this.resources.get(buffer);if (size) {this.currentMemory -= size;this.resources.delete(buffer);}}cleanup() {// 释放最旧的资源const entries = Array.from(this.resources.entries());entries.sort((a, b) => a[1] - b[1]);while (entries.length > 0 && this.currentMemory > this.maxMemory * 0.8) {const [buffer, size] = entries.shift();this.release(buffer);}}
}

最佳实践建议 💡

  1. 错误处理和监控
// 1. Worker错误处理器
class WorkerErrorHandler {static handle(error, context) {console.error(`Error in ${context}:`, error);if (error instanceof TypeError) {return this.handleTypeError(error);}if (error.message.includes('quota exceeded')) {return this.handleQuotaError(error);}return this.handleGenericError(error);}static handleTypeError(error) {return {type: 'type_error',message: error.message,recoverable: true};}static handleQuotaError(error) {return {type: 'quota_error',message: 'Memory quota exceeded',recoverable: false};}static handleGenericError(error) {return {type: 'generic_error',message: error.message,recoverable: true};}
}// 2. Worker监控
class WorkerMonitor {constructor() {this.metrics = new Map();this.startTime = Date.now();}recordMetric(workerId, metric) {if (!this.metrics.has(workerId)) {this.metrics.set(workerId, []);}this.metrics.get(workerId).push({timestamp: Date.now(),...metric});}getWorkerMetrics(workerId) {const metrics = this.metrics.get(workerId) || [];return {totalTasks: metrics.length,averageTaskTime: this.calculateAverageTime(metrics),errorRate: this.calculateErrorRate(metrics),throughput: this.calculateThroughput(metrics)};}calculateAverageTime(metrics) {const times = metrics.filter(m => m.duration).map(m => m.duration);return times.reduce((a, b) => a + b, 0) / times.length;}calculateErrorRate(metrics) {const errors = metrics.filter(m => m.error).length;return errors / metrics.length;}calculateThroughput(metrics) {const timeRange = Date.now() - this.startTime;return metrics.length / (timeRange / 1000);}
}// 3. 安全策略
class WorkerSecurity {constructor() {this.allowedOrigins = new Set();this.maxPayloadSize = 10 * 1024 * 1024; // 10MB}validateMessage(message) {if (this.exceedsPayloadSize(message)) {throw new Error('Message exceeds maximum size');}if (!this.isValidContent(message)) {throw new Error('Invalid message content');}return true;}exceedsPayloadSize(message) {const size = new Blob([JSON.stringify(message)]).size;return size > this.maxPayloadSize;}isValidContent(message) {// 实现消息内容验证逻辑return true;}
}

结语 📝

Web Workers为JavaScript提供了强大的并行计算能力,使得Web应用能够处理更复杂的任务。通过本文,我们学习了:

  1. Web Workers的基本概念和实现
  2. 高级功能和状态管理
  3. 性能优化技巧
  4. 错误处理和监控
  5. 安全性考虑

💡 学习建议:在使用Web Workers时,要注意平衡任务的粒度,避免过于频繁的通信开销。同时,要做好错误处理和资源管理,确保应用的稳定性。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

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

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

相关文章

26、正则表达式

目录 一. 匹配字符 .&#xff1a;匹配除换行符外的任意单个字符。 二. 位置锚点 ^&#xff1a;匹配输入字符串的开始位置。 $&#xff1a;匹配输入字符串的结束位置。 \b&#xff1a;匹配单词边界。 \B&#xff1a;匹配非单词边界。 三. 重复限定符 *&#xff1a;匹配…

Chrome远程桌面无法连接怎么解决?

Chrome远程桌面连接已停止工作 Chrome远程桌面是一款极为便捷的浏览器插件&#xff0c;能够帮助用户将自己的计算机连接到其他设备&#xff0c;无论是手机、平板电脑还是其他电脑。然而&#xff0c;在实际使用中&#xff0c;许多用户可能会面临各种各样的问题&#xff0c;比如…

备赛蓝桥杯之第十五届职业院校组省赛第一题:智能停车系统

提示&#xff1a;本篇文章仅仅是作者自己目前在备赛蓝桥杯中&#xff0c;自己学习与刷题的学习笔记&#xff0c;写的不好&#xff0c;欢迎大家批评与建议 由于个别题目代码量与题目量偏大&#xff0c;请大家自己去蓝桥杯官网【连接高校和企业 - 蓝桥云课】去寻找原题&#xff0…

基于AutoDL云计算平台+LLaMA-Factory训练平台微调本地大模型

1. 注册与认证 访问AutoDL官网&#xff1a;前往 AutoDL官网。 注册账号&#xff1a;完成注册流程。 实名认证&#xff1a;按照要求完成实名认证&#xff0c;以确保账号的合规性。 2. 选择GPU资源 进入算力市场&#xff1a;在官网首页点击“算力市场”菜单。 挑选GPU&#x…

C语言练习(19)

已知5个学生的4门课的成绩&#xff0c;要求求出每个学生的平均成绩&#xff0c;然后对平均成绩从高到低将各学生的成绩记录排序&#xff08;成绩最高的学生排在数组最前面的行&#xff0c;成绩最低的学生排在数组最后面的行&#xff09;。 #include <stdio.h> #include &…

微信小程序使用picker根据接口给的省市区的数据实现省市区三级联动或者省市区街道等多级联动

接口数据如上图 省市区多级联动&#xff0c;都是使用的一个接口通过传参父类的code。返回我们想要的数据 比如获取省就直接不要参数。市就把省得code传给接口&#xff0c;区就把市的code作为参数。 <picker mode"multiSelector" :range"mulSelect1" …

VOSK实现【离线中文语音】识别

Vosk是一款开源的离线语音识别工具包&#xff0c;具有以下功能&#xff1a; 多语言支持&#xff1a;能够对20多种语言和方言进行语音识别&#xff0c;如中文、英语、德语、法语、西班牙语等&#xff0c;可满足不同用户的语言需求。 模型轻量化&#xff1a;每种语言的模型大小仅…

【Maui】注销用户,采用“手势”点击label弹窗选择

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 方法一&#xff1a;前端绑定3.2 方法二&#xff1a;后端绑定3.3 注销用户的方法 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创…

macOS使用LLVM官方发布的tar.xz来安装Clang编译器

之前笔者写过一篇博文ubuntu使用LLVM官方发布的tar.xz来安装Clang编译器介绍了Ubuntu下使用官方发布的tar.xz包来安装Clang编译。官方发布的版本中也有MacOS版本的tar.xz&#xff0c;那MacOS应该也是可以安装的。 笔者2015款MBP笔记本&#xff0c;CPU是intel的&#xff0c;出厂…

中企出海:从国际投资建厂:投前投中投后重点事项

1. 投前重点事项 1.1 市场调研与分析 在国际投资建厂的投前阶段&#xff0c;市场调研与分析是至关重要的基础工作&#xff0c;它能够帮助企业全面了解目标市场&#xff0c;为后续决策提供有力依据。 市场规模与潜力&#xff1a;通过收集和分析目标国家或地区的经济数据、行业…

Git实用指南:忽略文件、命令别名、版本控制、撤销修改与标签管理

目录 1.忽略特殊文件 1.1.那如何配置我们需要忽略的文件的呢&#xff1f; 1.2.如何检验效果&#xff1f; 2.给命令配置别名 3.基本操作之版本回退 3.1.使用场景&#xff1a; 3.2.使用方法&#xff1a; 4.撤销修改 情况一&#xff1a;对于工作区的代码&#xff0c;还没…

Glary Utilities Pro 多语便携版系统优化工具 v6.21.0.25

Glary Utilities是一款功能强大的系统优化工具软件&#xff0c;旨在帮助用户清理计算机垃圾文件、修复系统错误、优化系统性能等。 软件功能 清理和修复&#xff1a;可以清理系统垃圾文件、无效注册表项、无效快捷方式等&#xff0c;修复系统错误和蓝屏问题。 优化和加速&…

Oracle 创建并使用外部表

目录 一. 什么是外部表二. 创建外部表所在的文件夹对象三. 授予访问外部表文件夹的权限3.1 DBA用户授予普通用户访问外部表文件夹的权限3.2 授予Win10上的Oracle用户访问桌面文件夹的权限 四. 普通用户创建外部表五. 查询六. 删除 一. 什么是外部表 在 Oracle 数据库中&#x…

基于FPGA的BPSK+costas环实现,包含testbench,分析不同信噪比对costas环性能影响

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.Verilog核心程序 4.完整算法代码文件获得 1.算法仿真效果 本作品是之前作品的改进和扩展&#xff1a; 1.m基于FPGA的BPSK调制解调通信系统verilog实现,包含testbench,包含载波同步_csdn基于fpga的bpsk-CSDN博客 2.m基于FP…

后端开发Web

Maven Maven是apache旗下的一个开源项目&#xff0c;是一款用于管理和构建java项目的工具 Maven的作用 依赖管理 方便快捷的管理项目依赖的资源&#xff08;jar包&#xff09;&#xff0c;避免版本冲突问题 统一项目结构 提供标准、统一的项目结构 项目构建 标准跨平台(…

前沿技术趋势洞察:2024年技术的崭新篇章与未来走向!

引言 时光飞逝&#xff0c;2024年已经来临&#xff0c;回顾过去一年&#xff0c;科技的迅猛进步简直让人目不暇接。 在人工智能&#xff08;AI&#xff09;越来越强大的今天&#xff0c;我们不再停留在幻想阶段&#xff0c;量子计算的雏形开始展示它的无穷潜力&#xff0c;Web …

【10.2】队列-设计循环队列

一、题目 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&#xff08;先进先出&#xff09;原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普…

博客之星2024年度总评选——我的年度创作回顾与总结

2024年&#xff0c;是我在CSDN博客上持续耕耘、不断成长的一年。在此&#xff0c;与大家分享一下我的年度创作回顾与总结。 一、创作成长与突破 在人工智能领域&#xff0c;技术迭代迅速&#xff0c;知识更新频繁。为了保持自己的竞争力&#xff0c;在今年&#xff0c;我始终…

IDEA运行Java项目总会报程序包xxx不存在

我的在另外一台电脑上跑是没有问题的&#xff0c;在新的电脑上跑的时候&#xff0c;又出现了这个恶心的问题...... 思来想去&#xff0c;唯一的问题就是我的mavn环境没的配置好 如何在本地部署mavn环境&#xff0c;这里推荐一篇很好的文章&#xff1a; Maven安装与配置&…

java 根据前端传回的png图片数组,后端加水印加密码生成pdf,返回给前端

前端传回的png图片数组&#xff0c;后端加水印加密码生成pdf&#xff0c;返回给前端 场景&#xff1a;重点&#xff1a;maven依赖controllerservice 场景&#xff1a; 当前需求&#xff0c;前端通过html2canvas将页面报表生成图片下载&#xff0c;可以仍然不满意。 需要java后…