主进程中发生了一个javascript错误_知道html5 Web Worker标准吗?能实现JavaScript的多线程?

js为什么是单线程?

主要是因为最开始javascript是单纯的服务于浏览器的一种脚步语言(那时候没有nodejs)。浏览器是为了渲染网页,通过dom与用户交互,如果一个线程需要给dom执行click事件,而另一个进程要删除这个dom,这2个动作可能同时进行,也可能先后进行(像java,c#等语言中会引入锁的概念,这样会变得异常复杂),那么就会造成很多不可预料的错误。

所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征。为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

浏览器是多线程的

浏览器打开一个tab,就会单独开一个进程,这个进程包含多个线程
主要包含的线程有:

GUI渲染线程
负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行
注意,GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。JS引擎线程
也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
JS引擎线程负责解析Javascript脚本,运行代码。
JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序
同样注意,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。事件触发线程
归属于浏览器而不是JS引擎,用来控制事件循环(可以理解,JS引擎自己都忙不过来,需要浏览器另开线程协助)
当JS引擎执行代码块如setTimeOut时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件线程中
当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
注意,由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)定时触发器线程
传说中的setInterval与setTimeout所在线程
浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)
因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。异步http请求线程
在XMLHttpRequest在连接后是通过浏览器新开一个线程请求
将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。
上面列出的线程之间,有一个重要的规则是:GUI渲染线程与JS引擎线程互斥,那么我们可以得出以下结论JS阻塞页面加载,那么在js运行的这段时间内,GUI的渲染会停止,这段时间内的界面交互,DOM的重绘与回流会停止,会被保存到待执行队列中,直到js线程空闲,才会执行这些队列。
我们用下面的一段代码和运行结果来说明这个机制:

    
5a58c79d0ab6fba30c56152277a02e50.gif


可以看到,一开始网页和动画正常运行,但是开始执行计算斐波那契数列后,动画就停止了,页面也停止响应鼠标的click事件了,直到recurFib(40)计算出结果后,动画才开始继续执行,而期间积攒的click事件也在一起被执行。这就解释了GUI渲染线程与JS引擎线程互斥。由于这个弊端HTML5提出Web Worker标准。

利用Web Worker开启一个子线程

Web Worker 有以下几个使用注意点。

1.同源限制
分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
2.DOM 限制
Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
3.通信联系
Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
4.脚本限制
Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
5.文件限制
Worker 线程无法读取本地文件,即不能打开本机的文件系统(file:),它所加载的脚本,必须来自网络。
创建Worker时,JS引擎向浏览器申请开一个子线程(子线程是浏览器开的,完全受主线程控制,而且不能操作DOM)
JS引擎线程与worker线程间通过特定的方式通信(postMessage API,需要通过序列化对象来与线程交互特定的数据)。
下面我们用worker的相关api来解决上面卡顿的问题。

    
// test.js子线程代码// 通过监听message来接受主线程中的消息addEventListener('message', function(res) {    // 子线程向主线程中发生消息    // 计算斐波那契数列,这个数列从第3项开始,每一项都等于前两项之和。    if(res.data === 'start') {        // 开始运算        console.log('收到主线程消息,开始运算')        function recurFib(n) {            if(n < 2){                // 主动关闭子线程                // this.close()                return n ;            }else {                return recurFib(n-1)+recurFib(n-2)            }        }        console.time("运算时间:")        // 计算n为40的结果        var count = recurFib(40)        console.timeEnd("运算时间:")        // 向主线程发送消息        console.log('运算完毕,发送消息给主线程!')        this.postMessage(count);    }})

运行结果:

1a7ab0049f69705279802cf5617b7c84.png

可以看到整个运行过程动画没有卡顿,也能响应click事件,所以在我们遇到大型计算的时候,请单独开启一个worker子线程来解决js线程阻塞GUI线程的问题。上文中只涉及到一部分worker API。

兼容性

aca56cb2fce32ef21c3f4b17077cb583.png


可以看到除了Opera Mini浏览器,连IE都能使用了,所以兼容性问题不大。

总结

  1. 由于javaScript的最初设计特点,采用了单线程的运行机制。
  2. 浏览器是多个线程相互协作来工作的,但是GUI渲染线程与JS引擎线程互斥
  3. js线程在运行时,会锁死GUI渲染线程,为了利用多核CPU的计算能力,HTML5提出Web Worker标准。
  4. Web Worker的使用有一些限制,比如说:同源限制,DOM限制,文件限制等,但能解决在js需要大量计算工作时,页面卡顿的问题。
  5. Web Worker实际上是js线程的一个子线程,理论上js还是单线程的。

学习如逆水行舟,不进则退,前端技术飞速发展,如果每天不坚持学习,就会跟不上,我会陪着大家,每天坚持推送博文,跟大家一同进步,希望大家能关注我,第一时间收到最新文章。

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

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

相关文章

C语言深度剖析书籍学习记录 第三章 预处理

宏 _LINE_ 表示正在编译的文件的行号_FILE_ 表示正在编译的文件的名字_DATE_ 表示编译时刻的日期字符串&#xff0c;例如: "25 Dec 2007"_TIME_ 表示编译时刻的时间字符串&#xff0c;例如: "12:30:55"_STDC_ 判断该文件是不是定义成标准 C 程序宏名的书写…

js正则限制字符串长度_正则笔记(3)万字长文,慎点。

正则讲了很久&#xff0c;也拖了很久&#xff0c;今天看看怎么用吧&#xff0c;后续更文应该会比较准勤快了。:-)书接上文【正则笔记(2)】。这次我们来看看正则的使用&#xff1a;(注&#xff1a;斜体表示为对应规则写出的正则表达式)一、 常用的正则表达式&#xff1a;1. 验证…

C语言深度剖析书籍学习记录 第四章 指针和数组

p 称为指针变量,p 里存储的内存地址处的内存称为 p 所指向的内存。 指针变量 p 里存储的任何数据都将被当作地址来处理一个基本的数据类型(包括结构体等自定义类型)加上“*” 号就构成了一个指针类型的模子。这个模子的大小是一定的&#xff0c;与“*”号前面的数据类型无 关。…

js中select下拉框重置_如何利用CSS3制作炫酷的下拉框

很多小伙伴都不清楚CSS3是做什么&#xff1f;用途是什么&#xff1f;接下来我就给展示一个css3制作一个炫酷下拉框。其实不只是这些&#xff0c;还有很多。CSS3是CSS(层叠样式表)技术的升级版本&#xff0c;于1999年开始制订&#xff0c;2001年5月23日W3C完成了CSS3的工作草案&…

select选择框必输校验_轮子这么多,我们为什么选择自研NewSQL

作者介绍李鑫&#xff0c;滴滴资深软件开发工程师&#xff0c;多年分布式存储领域设计及开发经验。曾参与NoSQL/NewSQL数据库Fusion、分布式时序数据库sentry、NewSQL数据库SDB等系统的设计开发工作。一、背景Fusion-NewSQL是由滴滴自研的在分布式KV存储基础上构建的NewSQL存储…

C语言深度剖析书籍学习记录 第五章 内存管理

常见的内存错误 定义了指针变量&#xff0c;但是没有为指针分配内存&#xff0c;即指针没有指向一块合法的内存。 结构体成员指针未初始化 很多初学者犯了这个错误还不知道是怎么回事。这里定义了结构体变量 stu&#xff0c;但是他没 想到这个结构体内部 char *name 这成员在定…

怎么改电脑网络ip地址_抛弃重启路由器获取ip地址方式,巧妙运用ip代理改IP工具...

网络是简单的也是复杂的&#xff0c;在如此庞大的网络世界里有太多的不确定因素&#xff0c;导致我们遇到IP限制问题&#xff0c;从而影响到我们的网络访问&#xff0c;而大家都知道&#xff0c;如果遇到ip被限制的问题&#xff0c;最快速直接的办法就是把被限制的ip更换一个新…

C语言深度剖析书籍学习记录 第六章 函数

函数的好处 1、降低复杂性:使用函数的最首要原因是为了降低程序的复杂性&#xff0c;可以使用函数来隐含信息&#xff0c;从而使你不必再考虑这些信息。2、避免重复代码段:如果在两个不同函数中的代码很相似&#xff0c;这往往意味着分解工作有误。这时&#xff0c;应该把两个…

如何把word分装到两个byte_如何核对两个Word文档的内容差别?同事加班半小时,我只花了30秒...

昨天下班前&#xff0c;老板突然发了两份Word文档过来&#xff0c;一份是原稿&#xff0c;还有一份是修订稿&#xff0c;叫我们找出两份文档的内容差别之处&#xff0c;我只花了30秒就搞定了&#xff0c;然后准时下班&#xff01;你想知道我是怎么操作的吗&#xff1f;下面小源…

stm32f767中文手册_ALIENTEK 阿波罗 STM32F767 开发板资料连载第五章 SYSTEM 文件夹

1)实验平台&#xff1a;alientek 阿波罗 STM32F767 开发板2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号&#xff0c;获取更多资料&#xff1a;正点原子第五章 SYSTEM 文件夹介绍第三章&#xff0c;我们介绍了如何在 MDK5 下建立 STM32F7 工程。在这个新建的工程之…

手机安卓学习 内核开发

官网开源代码 Documentation - MiCode/Xiaomi_Kernel_OpenSource - Sourcegraph Xiaomi 11T Pro GitHub - MiCode/Xiaomi_Kernel_OpenSource: Xiaomi Mobile Phone Kernel OpenSourceAndroid 开源项目 | Android Open Source Project google安卓官网 目录概览 参考…

vs 启动调用的目标发生异常_如何解决不可测、异常场景的问题?

阿里QA导读&#xff1a;在软件研发过程中&#xff0c;发布前跨多个系统的联调测试是不可或缺的一环&#xff0c;而在联调过程中&#xff0c;经常会遇到一些比较棘手的困难&#xff0c;阻塞整个联调进程。其中比较典型的有&#xff1a;第三方的研发节奏不一致&#xff0c;导致无…

Linux内核 scatterlist介绍

scatterlist 物理内存的散列表。通俗讲&#xff0c;就是把一些分散的物理内存&#xff0c;以列表的形式组织起来 诞生背景 假设有三个模块可以访问memory&#xff1a;CPU、DMA控制器和某个外设。CPU通过MMU以虚拟地址&#xff08;VA&#xff09;的形式访问memory&#xff1b;…

Linux内核 crypto文件夹 密码学知识学习

密码算法分类 对称算法非对称算法消息摘要&#xff08;单向哈希&#xff09;算法这些算法作为加密函数框架的最底层&#xff0c;提供加密和解密的实际操作。这些函数可以在内核crypto文件夹下&#xff0c;相应的文件中找到。不过内核模块不能直接调用这些函数&#xff0c;因为…

Linux crypto相关知识的汇总 Linux加密框架crypto中的算法和算法模式(一)

Linux加密框架中的算法和算法模式 Linux加密框架中的算法和算法模式&#xff08;一&#xff09;_家有一希的博客-CSDN博客 加密框架支持的密码算法主要是对称密码算法和哈希算法&#xff0c;暂时不支持非对称密码算法。除密码算法外&#xff0c;加密框架还包括伪随机数生成算法…

Linux crypto相关知识的汇总 Linux加密框架crypto对称算法和哈希算法加密模式

参考链接 Linux加密框架中的算法和算法模式&#xff08;二&#xff09;_家有一希的博客-CSDN博客 对称算法 分组算法模式 ECB模式 ECB模式下&#xff0c;明文数据被分为大小合适的分组&#xff0c;然后对每个分组独立进行加密或解密如下图所示如果两个明文块相同&#xff0c…

Linux加密框架中的算法和算法模式

参考链接 Linux加密框架中的算法和算法模式&#xff08;三&#xff09;_家有一希的博客-CSDN博客 对称算法 14 如上所示&#xff0c;在arc4.c中定义了两个与RC4算法相关的算法实现&#xff0c;分别为arc4和ecb(arc4)&#xff0c;其中arc4是RC算法的算法实现&#xff0c;而ecb…

Linux加密框架crypto AES代码相关

例子 aes_generic.c - crypto/aes_generic.c - Linux source code (v5.15.11) - Bootlin static struct crypto_alg aes_alg {.cra_name "aes",.cra_driver_name "aes-generic",.cra_priority 100,.cra_flags CRYPTO_ALG_TYPE_CIPHER,.cra_blocks…

Linux加密框架 crypto RC4

参考链接 arc4.h Linux加密框架中的主要数据结构&#xff08;一&#xff09;_家有一希的博客-CSDN博客 头文件 arc4.h - include/crypto/arc4.h - Linux source code (v5.15.11) - Bootlin实现代码 arc4.c arc4.c - crypto/arc4.c - Linux source code (v5.15.11) - Bootlin…