JavaScript之多线程和Event-Loop

引子几乎在每一本JS相关的书籍中,都会说JS是单线程的,JS是通过事件队列(Event Loop)的方式来实现异步回调的。 对很多初学JS的人来说,根本搞不清楚单线程的JS为什么拥有异步的能力,所以,我试图从进程、线程的角度来解释这个问题。 CPU说到CPU和进程、线程,对计算机操作系统有过学习和了解的同学应该比较熟悉。 计算机的核心是CPU,它承担了所有的计算任务。 它就像一座工厂,时刻在运行。 假定工厂的电力有限,一次只能供给一个车间使用。 也就是说,一个车间开工的时候,其他车间都必须停工。 背后的含义就是,单个CPU一次只能运行一个任务。 进程就好比工厂的车间,它代表CPU所能处理的单个任务。 进程之间相互独立,任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。 CPU使用时间片轮转进度算法来实现同时运行多个进程。 CPU、进程、线程之间的关系从上文我们已经简单了解了CPU、进程、线程,简单汇总一下。 进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位)线程是cpu调度的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)不同进程之间也可以通信,不过代价较大单线程与多线程,都是指在一个进程内的单和多浏览器是多进程的我们已经知道了CPU、进程、线程之间的关系,对于计算机来说,每一个应用程序都是一个进程, 而每一个应用程序都会分别有很多的功能模块,这些功能模块实际上是通过子进程来实现的。 对于这种子进程的扩展方式,我们可以称这个应用程序是多进程的。 而对于浏览器来说,浏览器就是多进程的,我在Chrome浏览器中打开了多个tab,然后打开windows控制管理器: 如上图,我们可以看到一个Chrome浏览器启动了好多个进程。总结一下: 浏览器是多进程的每一个Tab页,就是一个独立的进程浏览器包含了哪些进程主进程 协调控制其他子进程(创建、销毁)浏览器界面显示,用户交互,前进、后退、收藏将渲染进程得到的内存中的Bitmap,绘制到用户界面上处理不可见操作,网络请求,文件访问等第三方插件进程 每种类型的插件对应一个进程,仅当使用该插件时才创建GPU进程 用于3D绘制等渲染进程,就是我们说的浏览器内核 负责页面渲染,脚本执行,事件处理等每个tab页一个渲染进程那么浏览器中包含了这么多的进程,那么对于普通的前端操作来说,最重要的是什么呢? 答案是渲染进程,也就是我们常说的浏览器内核 浏览器内核(渲染进程)从前文我们得知,进程和线程是一对多的关系,也就是说一个进程包含了多条线程。 而对于渲染进程来说,它当然也是多线程的了,接下来我们来看一下渲染进程包含哪些线程。 GUI渲染线程 负责渲染页面,布局和绘制页面需要重绘和回流时,该线程就会执行与js引擎线程互斥,防止渲染结果不可预期JS引擎线程 负责处理解析和执行javascript脚本程序只有一个JS引擎线程(单线程)与GUI渲染线程互斥,防止渲染结果不可预期事件触发线程 用来控制事件循环(鼠标点击、setTimeout、ajax等)当事件满足触发条件时,将事件放入到JS引擎所在的执行队列中定时触发器线程 setInterval与setTimeout所在的线程定时任务并不是由JS引擎计时的,是由定时触发线程来计时的计时完毕后,通知事件触发线程异步http请求线程 浏览器有一个单独的线程用于处理AJAX请求当请求完成时,若有回调函数,通知事件触发线程当我们了解了渲染进程包含的这些线程后,我们思考两个问题: 为什么 javascript 是单线程的为什么 GUI 渲染线程为什么与 JS 引擎线程互斥为什么 javascript 是单线程的首先是历史原因,在创建 javascript 这门语言时,多进程多线程的架构并不流行,硬件支持并不好。 其次是因为多线程的复杂性,多线程操作需要加锁,编码的复杂性会增高。 而且,如果同时操作 DOM ,在多线程不加锁的情况下,最终会导致 DOM 渲染的结果不可预期。 为什么 GUI 渲染线程与 JS 引擎线程互斥这是由于 JS 是可以操作 DOM 的,如果同时修改元素属性并同时渲染界面(即 JS线程和UI线程同时运行), 那么渲染线程前后获得的元素就可能不一致了。 因此,为了防止渲染出现不可预期的结果,浏览器设定 GUI渲染线程和JS引擎线程为互斥关系, 当JS引擎线程执行时GUI渲染线程会被挂起,GUI更新则会被保存在一个队列中等待JS引擎线程空闲时立即被执行。 ...

November 2, 2019 · 1 min · jiezi

详细判断浏览器运行环境可能是最全的判断值得一看

关注Uzero公众号,更多前端小干货等着你喔! 前言看到标题,大家就能想起这个需求在很多项目上都能用到。我们部署在Web服务器上的前端应用,既可以用PC浏览器访问,也可以用手机浏览器访问,再加上现在智能设备的推广,我们甚至能在车载系统、穿戴设备和电视平台上访问。 设备的多样化让用户无处不在,有时候我们需要根据不同的浏览器运行环境做出对应的处理。浏览器是JavaScript的承载体,我们可以从浏览器上获取相关的信息,来进一步处理我们的业务逻辑。 然而浏览器品牌众多,有些浏览器使用的标准也不太一样,造就了难以统一的判断。下面我大概罗列一下常用的浏览器品牌和在什么情况下使用浏览器运行环境判断。浏览器相关统计数据可以参考这里。 国际五大浏览器品牌:按照全球使用率降序排列Google Chrome:Windows、MacOS、Linux、Android、iOSApple Safari:MacOS、iOSMozilla Firefox:Windows、MacOS、Linux、Android、iOSASA Opera:Windows、MacOS、Linux、Android、iOSMicrosoft Internet Explorer或Microsoft Edge:Windows国产常用浏览器品牌:按照国内使用率降序排列,普遍基于开源项目Chromium进行开发微信浏览器QQ浏览器UC浏览器2345浏览器搜狗浏览器猎豹浏览器遨游浏览器百度浏览器:百度在2019年04月30日宣布停止服务其他浏览器:很多很多,数不清,我就不列出来了顺便吐槽一下这个不要脸的红芯浏览器,明明就是基于Chromium进行二次开发再套多一层外壳,还非得说自己开发的浏览器是世界第五大浏览器,偷吃不抹嘴,还是被眼尖的网友发现了。详情请戳one、two、three。。。。 使用场景判断用户浏览器是桌面端还是移动端,显示对应的主题样式判断用户浏览器是Android端还是iOS端,跳转到对应的App下载链接判断用户浏览器是微信端还是H5端,调用微信分享或当前浏览器分享获取用户浏览器的内核和载体,用于统计用户设备平台分布区间获取用户浏览器的载体版本,用于提示更新信息其实还有很多使用场景,就不一一举例了原理针对处理一个这样的使用场景,其实有一个比较专业的名字,叫做浏览器指纹。我们上面谈到的需求也只是浏览器指纹方案里面的一小部分,而我们需要使用到的浏览器指纹就是UserAgent。 这个UserAgent是何方神圣呢,中文翻译过来就是用户代理。引用百度的定义,就是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器载体及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。而这些信息也足够我们去判断浏览器运行环境了。 准备目前网上很多解决方法都只是针对系统是否是桌面端还是移动端,Android端还是iOS端,部分浏览器载体的判断和获取等等,没有一个比较完美或者终极的解决方案。 因此我用了很多测试平台整理出一个比较全面的解决方案。这个方案包含浏览器系统及版本、浏览器平台、浏览器内核及版本、浏览器载体及版本、浏览器外壳及版本。 而此方案也是基于navigator.userAgent获取相关浏览器信息(如下),再通过系统、平台、内核、载体、外壳的特有字段进行归类统一,整理出一个完整的浏览器运行环境。 const ua = navigator.userAgent.toLowerCase();// 输出"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"浏览器信息:权重按照以下降序排列浏览器系统:所运行的操作系统,包含Windows、MacOS、Linux、Android、iOS浏览器平台:所运行的设备平台,包含Desktop桌面端、Mobile移动端浏览器内核:浏览器渲染引擎,包含Webkit、Gecko、Presto、Trident浏览器载体:五大浏览器品牌,包含Chrome、Safari、Firefox、Opera、Iexplore/Edge浏览器外壳:基于五大浏览器品牌的内核进行开发,再套一层自研技术的外壳,如国内众多浏览器品牌获取UserAgent是否包含字段:判断是否包含系统、平台、内核、载体、外壳的特有字段const testUa = regexp => regexp.test(ua);获取UserAgent对应字段的版本const testVs = regexp => (ua.match(regexp) + "").replace(/[^0-9|_.]/ig, "").replace(/_/ig, ".");方案上述准备工作完成后,我们就按照权重(<font color="#f66">系统 + 系统版本 > 平台 > 内核 + 载体 + 内核版本 + 载体版本 > 外壳 + 外壳版本</font>)根据系统、平台、内核、载体、外壳的特有字段来归类统一浏览器运行环境。 ...

October 17, 2019 · 4 min · jiezi

11JavaScript-线程机制与事件机制

JavaScript线程机制与事件机制一、进程与线程进程(process)程序的一次执行,它占有一片独有的内存空间。可以通过windows任务管理器查看进程。线程(thread)是进程内的一个独立执行单元。是程序执行的一个完整流程。是CPU的最小调度单元。进程与线程图解 相关知识应用程序必须运行在某个进程的某个线程上。一个进程中至少有一个运行的线程:主线程,进程启动后自动创建。一个进程中也可以同时运行多个线程,我们会说程序是多线程运行的。一个进程内的数据可以供其中的多个线程中直接共享。多个进程之间的数据是不能直接共享的。线程池(thread pool):保存多个线程对象的容器,实现线程对象的反复利用。相关问题(1)何为多进程与多线程? 多进程运行:一个应用程序可以同时启动多个实例运行。多线程:在一个进程内,同时有多个线程运行。(2)比较单线程与多线程? 多线程 优点:能有效提升CPU的利用率。缺点: 创建多线程开销。线程间切换开销。死锁与状态同步问题。单线程 优点:顺序编程简单易懂。缺点:效率低。(3)JS是单线程还是多线程? JS是单线程运行的。但是使用H5中的 Web Workers可以多线程运行。(4)浏览器运行是单线程还是多线程? 浏览器都是多线程运行的。(5)浏览器运行是单进程还是多进程? 有的是单进程: 老版Firefox老版IE有的是多进程: Chrome新版Firefox新版IE如何查看浏览器是否是多进程运行的呢? 任务管理器==>进程二、浏览器内核(1)浏览器内核是支撑浏览器运行的最核心的程序。 (2)不同的浏览器内核不一样: Chrome,Safari:webkitFirefox:GeckoIE:Trident360,搜狗等国内浏览器:Trident+webkit(3)内核由很多模块组成: 主线程 js引擎模块:负责js程序的编译与运行。html,css文档解析模块:负责页面文本的解析。DOM/CSS模块:负责DOM/CSS在内存中的相关处理。布局和渲染模块:负责页面的布局和效果的绘制(内存中的对象)分线程 定时器模块:负责定时器的管理。DOM事件响应模块:负责事件的管理。网络请求模块:负责服务器请求(常规/ajax)。三、定时器引发的思考(1)定时器真是定时执行的吗? 定时器并不能保证真正定时执行。一般会延迟一丁点(可以接受), 也有可能延迟很长时间(不能接受)。<button id="btn">启动定时器</button>document.getElementById('btn').onclick = function () { var start = Date.now() console.log('启动定时器前...') setTimeout(function () { console.log('定时器执行了', Date.now()-start) }, 200) console.log('启动定时器后...')} 给上面回调函数加一个长时间的任务: document.getElementById('btn').onclick = function () { var start = Date.now() console.log('启动定时器前...') setTimeout(function () { console.log('定时器执行了', Date.now()-start) }, 200) console.log('启动定时器后...') // 做一个长时间的工作 for (var i = 0; i < 1000000000; i++) {}}结果: ...

June 27, 2019 · 2 min · jiezi

知识整理至浏览器篇

上一篇整理到HTML部分,发现有些知识点属于浏览器范畴,就单独出一篇来专门归纳。传送门:知识整理之HTML篇介绍一下你对浏览器内核的理解?主要分成两个部分:渲染引擎(Render Engine)和JS引擎。渲染引擎:负责取得网页的内容(html,xml和图像等),整理讯息(例如假如css),以及计算网页的显示方式,然后输出到显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不同。所有网页浏览器、电子邮件客户端以及它需要编辑、显示网络内容的应用程序都需要内核。JS引擎:解析和执行JavaScript来实现网页的动态效果。最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向与只指渲染引擎。关于浏览器工作原理详解,请移步至:浏览器工作原理详解常见的浏览器内核有哪些?IE浏览器内核:Trident内核,也被称为IE内核Chrome浏览器内核:Chromium内核 → Webkit内核 → Blink内核Firefox浏览器内核:Gecko内核,也被称Firefox内核Safari浏览器内核:Webkit内核Opera浏览器内核:最初是自主研发的Presto内核,后跟随谷歌,从Webkit到Blink内核360浏览器、猎豹浏览器内核:IE+Chrome双内核搜狗、遨游、QQ浏览器内核:Trident(兼容模式)+ Webkit(高速模式)百度浏览器、世界之窗内核:IE内核未完待续

January 28, 2019 · 1 min · jiezi