Web Worker:JS多线程的伪解药?

news2024/11/23 17:18:17

前言

在前端开发领域,JavaScript 的单线程限制一直是一个难以忽视的挑战。当谈到解决JavaScript的单线程限制时,HTML5引入的Web Worker被普遍认为是一剂解药💊。同时,业界中大量的文章也是聚焦于讨论web worker的神奇力量。然而,本文将另辟蹊径,和您一同探索Web Worker神秘的另一面。

js单线程限制及多线程能力的需求

js的一大特点就是单线程。对于单线程,一句最经典的概述就是“同一时间只能执行一个任务”。

在JavaScript设计之初,其单线程模型是由其主要用途和初衷所决定的。JavaScript作为一门浏览器端的脚本语言,最初的主要任务是处理用户交互。设想一下,如果JavaScript被设计为多线程,那么在用户交互中进行多线程同步操作DOM,为了保证准确性必然会引发竞态分配等复杂问题。另外,对于客户端来说也可能引发性能和资源消耗等多种复杂问题,这时的多线程在这个背景下反而显得过于臃肿。

随着Web技术的不断演进,JavaScript的单线程模型已经无法满足日益复杂的业务需求和以及带来的性能要求。为了解决这些问题,JavaScript引入了一些如ajaxsetTimeoutrequestAnimationFrame等机制,但需要明确的是,这些机制不过是通过EventLoop来制造的多线程假象,其并没有改变JavaScript单线程的本质。

至今,现代Web应用中用户交互变得越来越复杂,以及数据处理需求的增加,JavaScript应用需要更强的计算能力和更快的响应性,单线程模型面临着着挑战愈发严重。这就引出了一个关键问题:如何在保持JavaScript的单线程特性的同时,充分利用多核处理器来提高性能以满足用户的需求?在这样的背景下,Web Worker技术应运而生。

web worker的定义

或许在您的项目中尚未使用过Web Worker,但实际上它已经存在了很长时间。早在2009年,W3C便提出了 Web Worker 草案,2011年正式称为HTML5标准的一部分。

Image Description

W3C对Web Worker的定义如下:

an API for running scripts in the background independently of any user interface scripts.

兼容性

image.png

一个最最最最最简易明了的示例🌰
 
// 主线程代码
const worker = new Worker('worker.js');
worker.postMessage('Hello from the main thread!');
worker.onmessage = (event) => {
  console.log('Message from Web Worker:', event.data);
};

// worker.js
self.onmessage = (event) => {
  console.log('Message from main thread:', event.data);
  self.postMessage('Hello from the Web Worker!');
};

其他类型扩展

除了专用worker类型(Dedicated Web Worker),还有两种特殊的 Web Worker:SharedWorer和ServiceWorker。

  • SharedWorker可以在多个浏览器Tab中访问到同一个Worker实例, 可实现多Tab共享数据, 如共享webSocket连接等。然而看起来很美好, 但兼容性问题一度严重。特别是safari从12年ios5开始支持,到在ios7~15中一度不支持,再到ios16又支持,真是一波三折纠结死了!
  • ServiceWorker可以拦截和处理网络请求,实现离线缓存、推送通知和其他高级网络功能,也非常有意思。做过PWA的同学知道SW是其核心一环。

sharedWorker兼容性:

image.png

Web Worker 的优势🚀

Web Worker与主线程相互独立,可以在不影响主线程性能的情况下执行一些耗时操作而不会阻塞主线程,特别是在处理复杂任务和长时间运行的操作时非常有用。它的主要优势如下:

  • 独立运行:Web Worker在一个独立的线程中运行,与主线程互不干扰。这可以避免主线程因执行耗时操作而卡顿,从而提高页面的响应速度和用户体验。
  • 隔离机制:Web Worker无法直接访问或操作DOM元素。这种隔离机制可以防止潜在的页面修改和恶意攻击,确保网页的安全性和稳定性。
  • 多线程异步执行: Web Worker允许您在标签页进程中创建多个独立线程,每个线程都可以在不同的内核上执行,因此可以实现并行计算。

Web Worker的实际应用场景

在实际项目中,Web Worker更适合处理以下场景:

  • 计算密集型任务:例如,数据分析、图像处理、加密算法等。这些任务通常耗时较长且对 CPU性能要求较高。通过将这些任务委托给Web Worker,可以避免阻塞主线程,从而保持应用的响应性。
  • 异步操作:当需要执行一些异步操作时,例如从服务器获取数据,可以使用Web Worker来避免因为等待异步操作完成而导致的主线程卡顿。
  • 人工智能:Web Worker可以用于处理机器学习模型的训练或推断时的并行计算,从而提高模型的训练速度和响应性。

Web Worker的局限性

  • 兼容性问题:尽管HTML5已经普及,但Web Worker在大多数厂商的浏览器中仅在最新的大版本中支持,在旧版本中支持并不好。这导致开发者在实际项目中可能会放弃使用Web Worker。

  • 资源限制:无法直接访问DOM、同源策略、无法读取本地文件等等。

  • 编程复杂性:使用Web Worker需要处理线程间的通信,这增加了编程的复杂性。对于简单的任务使用Web Worker可能并不划算。

  • 安全性问题:因Web Worker是在后台运行的多线程,所以更隐蔽,由此也带来了新的安全问题:如恶意脚本的注入以利用Web Worker大规模执行多线程攻击来放大攻击效果、恶意创建大量web worker并让它们执行高负载的任务而导致浏览器崩溃、importScripts没有跨域限制可能会加载不受信任的脚本从而导致安全漏洞等等。

Web Worker的通信效率问题

除了以上局限性,Web Worker的通信效率问题也是值得注意的一点。

  • 无法共享内存: 与传统多线程编程不同,Web Worker不能直接共享内存,主页面与worker之间的数据传递的是通过拷贝而不是共享来完成的。因此在如大文件传输场景下可能会消耗大量内存和处理时间。

  • 数据序列化问题: 当主线程与Web Worker之间在数据交换时需要对数据进行序列化和反序列化,序列化会阻塞发送方,而反序列化会阻塞接收方。因此即使是小型数据,也需要经过这一过程。这可能在频繁通信的情况下积累成为性能瓶颈。

  • postMessage:postMessage方法本身并不是导致通信效率低下的主要原因,而是由于如Worker线程需要频繁地向主线程发送大量消息,或者消息体积较大等其他因素造成。这可能会导致主线程处理消息的速度跟不上Worker线程发送消息的速度,从而引起通信拥塞和性能问题。

主线程Web Worker数据传输数据传输postMessage(data)onmessage(event)序列化数据发送序列化数据反序列化数据postMessage(replyData)序列化回复数据发送序列化回复数据反序列化回复数据主线程Web Worker

通信效率带来的问题

由于通信效率的限制,Web Worker不适用于实时任务。由于消息传递的开销和可能的网络延迟,Web Worker无法保证实时性。因此,对于在线游戏、视频会议等一些需要实时响应场景,使用Web Worker可能不是最佳选择。

思考:有了 Web Worker API,JavaScript 是否真的变成了一门多线程语言?

在 MDN 的web worker的”线程安全“一节中提到:

“The Worker interface spawns real OS-level threads”

从底层技术角度来看,Web Worker确实具备多线程的特性。然而这与传统多线程编程语言(如Java或C++)有所不同。如,JavaScript中的主线程与Web Worker之间采用的是消息传递来通信,而不是直接共享内存。这意味着Web Worker之间无法直接共享数据,而传统多线程语言则可以直接共享内存,从而实现更直接和高效的线程间通信。

尽管Web Worker从底层技术上看具备多线程的特性,但如今JavaScript的主要应用领域仍然是处理用户界面和用户交互,Web Worker的引入主要是为了改善前端应用的响应性,使其能够更好地处理一些计算密集型任务,而不是将JavaScript彻底转变为多线程编程语言。

总结而言,尽管Web Worker API为JavaScript提供了一定程度的多线程支持,但JavaScript仍然是一门主要依赖于单线程执行的编程语言,Web Worker并没有改变JavaScript的单线程本质。

js多线程技术的未来展望

未来的js多线程应该具有更好的性能、更好的响应性以及更多的并行计算能力,随着Web技术不断发展,多线程前景越发广阔。如:

  • 浏览器引擎及硬件加速技术的不断发展,使得在浏览器中处理复杂的多线程任务更为可行;
  • WebAssembly等新技术的融合可能带来的机遇;
  • 随着ECMAScript标准的不断发展,可以期待更多多线程相关的功能和API的引入,以更好地支持并行计算。

总结

综上所述,Web Worker作为一种在前端开发中多线程的工具,的确有其独特的优势。然而,我们必须明白,尽管它被广泛视为解决JavaScript单线程问题的一种方式,但它并没有从根本上改变JavaScript的单线程本质。在使用Web Worker时,我们仍然需要面对资源限制、通信开销以及安全性等问题。因此,可以说Web Worker是一种”伪解药“。它有助于缓解JavaScript单线程的限制,但并非银弹。在未来,我们期待JavaScript多线程领域的进一步发展,以实现Web能力的持续提升🚀!


原文链接:https://juejin.cn/post/7274146202496565306
 

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

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

相关文章

Banana Pi BPI-M6开源硬件开发板介绍以及与 Raspberry Pi 5 的比较

Banana Pi BPI-M6 Banana Pi BPI-M6是Banana-Pi组织最新开发的一款类似于Raspberry Pi的单板计算机,具有相同的尺寸格式和相似的功能。 今天我想向您介绍这些功能,并将它们与新的 Raspberry 5 提供的功能进行一些比较。 Raspberry Pi是英国 Raspberry P…

Cesium教程(二十):动态加载图片

1、效果预览 备注: 箭头图片可以去这里下载:箭头下载地址 2、代码编写 创建容器 <div id="cesiumContainer" class="fullSize"

软件版本控制系统VCS工具——cvs vss svn git

版本控制 版本控制系统&#xff08;Version Control System&#xff0c;VCS&#xff09;是用于跟踪和管理源代码和文档的工具。可追踪和管理修改历史&#xff0c;包括修改的内容、时间、作者等信息。有助于团队协作、追踪变更、恢复历史版本等。VCS的主要目的是帮助团队协作开…

竞赛选题 深度学习机器视觉车道线识别与检测 -自动驾驶

文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分…

Pytest系列(16)- 分布式测试插件之pytest-xdist的详细使用

前言 平常我们功能测试用例非常多时&#xff0c;比如有1千条用例&#xff0c;假设每个用例执行需要1分钟&#xff0c;如果单个测试人员执行需要1000分钟才能跑完当项目非常紧急时&#xff0c;会需要协调多个测试资源来把任务分成两部分&#xff0c;于是执行时间缩短一半&#…

【gogogo专栏】golang并发编程

golang并发编程 并发编程的工具goroutine介绍协程管理器sync.WaitGroup channel介绍readChannel和writeChannelclose的用法select的用法 通讯示例总结 并发编程的工具 在golang中&#xff0c;并发编程是比较简单的&#xff0c;不像java中那么麻烦&#xff0c;golang天然的支持协…

便携式电能质量分析仪

产品简介 KDZD5000电能质量分析仪是我公司精心研制的现场测试的三相、多功能、智能化、人机操作简洁的综合型测试仪器。具有容易使用&#xff0c;超大液晶彩屏显示&#xff0c;高分辨率&#xff0c;中英文双语操作界面&#xff0c;防振结构外壳等特点。可同时测量4路电流&…

Cesium 展示——拖拽点移动相邻线也跟着更新

文章目录 需求分析1. 获取所要移动实体的 ID2. 移动点相邻线跟着更新移动3. 注意4. 其他需求 实现 拖拽点移动相邻线也跟着更新 拖拽前 点击拖拽 拖拽后 分析 1. 获取所要移动实体的 ID 在Cesium中获取指定(x, y)位置处的实体ID,你可以通过以下步骤实现: 首先,使用Cesi…

2023年【化工自动化控制仪表】考试报名及化工自动化控制仪表考试试卷

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年化工自动化控制仪表考试报名为正在备考化工自动化控制仪表操作证的学员准备的理论考试专题&#xff0c;每个月更新的化工自动化控制仪表考试试卷祝您顺利通过化工自动化控制仪表考试。 1、【单选题】CENTUMCS30…

【自定义控制器View的懒加载 Objective-C语言】

一、控制器的View懒加载 1.大家对这个懒加载是什么概念: 把上节课的代码command + C、command + V、保存一个副本,把副本命名为03-控制器的view的懒加载: 是不是用到的时候,再去加载,然后呢,只加载一次,对吧, 那这些重复的,我就删掉了啊, 删掉 控制器里面: 这个删…

PV与PVC

emptyDir存储卷 概述&#xff1a; 当Pod被分配给节点时&#xff0c;首先创建emptyDir卷&#xff0c;并且只要该Pod在该节点上运行&#xff0c;该卷就会存在。正如卷的名字所述&#xff0c;它最初是空的。Pod 中的容器可以读取和写入emptyDir卷中的相同文件&#xff0c;尽管该…

软件开发中常见的设计原则

软件开发中常见的设计原则 1. 单一责任原则2. 开放封闭原则3. 里氏替换原则4. 接口分离原则5. 依赖倒置原则6. 迪米特法则7. 合成复用原则8. 共同封闭原则9. 稳定抽象原则10. 稳定依赖原则 简写全拼中文翻译SRPThe Single Responsibility Principle单一责任原则OCPThe Open Clo…

Flink--Data Source 介绍

Data Source 简介 Flink 做为一款流式计算框架&#xff0c;它可用来做批处理&#xff0c;即处理静态的数据集、历史的数据集&#xff1b;也可以用来做流处理&#xff0c;即实时的处理些实时数据流&#xff0c;实时的产生数据流结果&#xff0c;只要数据源源不断的过来&#xff…

前端面试题之Javascript篇

一、JavaScript基础 1、数组有哪些方法 添加/删除元素 push() 向尾部添加元素pop() 从尾部提取一个元素shift() 从首端提取元素unshift() 从首端添加元素splice(start, deleteCount, item1...itemN) start表示开始计算的索引&#xff0c;deleteCount表示从start开始计算的元…

PTA_乙级_1006

思路&#xff1a;把数字的每一位都取出来&#xff0c;然后for循环把字符输入 #include <iostream> #include <string> using namespace std;int main() {int n;cin >> n;int b n / 100; // 计算百位数int s (n % 100) / 10; // 计算十位数int g n…

大学智能电表改造解决方案

随着科技的不断发展&#xff0c;我国高等教育院校在基础设施方面也在不断进行智能化升级。电力系统作为大学校园的重要组成部分&#xff0c;对其进行智能化改造已成为当前高校建设的热门话题。本文将详细介绍大学智能电表改造解决方案&#xff0c;以期为我国高校的电力系统智能…

Unity Input System最简单使用

开始学的是 Input Manager 比较好理解&#xff0c;Input System却不好理解&#xff0c;教程也找了很多&#xff0c;感觉都讲的不清楚&#xff0c;我这里做一个最简单的用 Input System 添加鼠标左键和右键的效果。 1. 安装 Input System 包 首先这个功能不是内置的&#xff0…

Linux内核有什么之内存管理子系统有什么第二回 —— 单刀直入

接前一篇文章&#xff1a;Linux内核有什么之内存管理子系统有什么第一回 —— 引言 一、单刀直入 —— 一切从malloc开始 想必大家都使用过malloc()&#xff0c;malloc的全称是memory allocation&#xff0c;中文叫做动态内存分配。其用于申请一块连续的指定大小的内存块区域以…

公众号生成链接

登录公众号 后点击左侧“设置与开发” 下 公众号设置&#xff0c;点击账号详情&#xff0c;然后查看源代码&#xff0c;搜索uin_base64 找到参数&#xff0c;然后设置到地址_biz上。在微信中打开就可以链接到微信公众号。 如下&#xff1a;

CSS 网页布局

网页布局有很多种方式&#xff0c;一般分为以下几个部分&#xff1a;头部区域、菜单导航区域、内容区域、底部区域&#xff1a; 1&#xff09;、头部区域位于整个网页的顶部&#xff0c;一般用于设置网页的标题或者网页的logo。 <style> body { margin: 0; } /* 头部样…