前端H5开发前端开发

从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理

2019-04-18  本文已影响1人  海之深处爱之港湾

一、区分进程和线程

形象比喻

* 进程是一个工厂,工厂有它独立的资源;

* 工厂之间相互独立;

* 线程是工厂里边的工人,多个工人协同完成任务;

* 工厂内有一个或多个工人;

* 工人之间共享空间

完善概念

* 工厂的资源 -> 系统分配的内存(独立的一块内存)

* 工厂之间的相互独立 -> 进程之间相互独立

* 多个工人协作完成任务 -> 多个线程在进程中协作完成任务

* 工厂内有一个或多个工人 -> 一个进程由一个或多个线程组成

* 工人之间共享空间 ->同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)

tips

二、浏览器是多进程的

三、浏览器都包含哪些进程?

强化记忆:在浏览器中打开一个网页相当于新起了一个进程(进程内有自己的多线程)

四、浏览器多进程的优势

相比于单进程浏览器,多进程有如下优点:

* 避免单个page crash影响整个浏览器

* 避免第三方插件crash影响整个浏览器

* 多进程充分利用多核优势

* 方便使用沙盒模型隔离插件等进程,提高浏览器稳定性

简单点理解:如果浏览器是单进程,那么某个Tab页崩溃了,就影响了整个浏览器,体验有多差;同理如果是单进程,插件崩溃了也会影响整个浏览器;而且多进程还有其它的诸多优势。。。

五、浏览器内核(渲染进程)

浏览器的渲染进程是多线程的

那些线程?

六、Browser进程和浏览器内核(Renderer进程)的通信过程

七、简单梳理下浏览器渲染流程

* 浏览器输入url,浏览器主进程接管,开一个下载线程,
然后进行 http请求(略去DNS查询,IP寻址等等操作),然后等待响应,获取内容,
随后将内容通过RendererHost接口转交给Renderer进程

* 浏览器渲染流程开始

浏览器器内核拿到内容后,渲染大概可以划分成以下几个步骤:

* 解析html建立dom树

* 解析css构建render树(将CSS代码解析成树形的数据结构,然后结合DOM合并成render树)

* 布局render树(Layout/reflow),负责各元素尺寸、位置的计算

* 绘制render树(paint),绘制页面像素信息

* 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上。

八、load事件与DOMContentLoaded事件的先后

load事件与DOMContentLoaded事件的先后?

所以,顺序是:DOMContentLoaded -> load

九、css加载是否会阻塞dom树渲染?

这里说的是头部引入css的情况

首先,我们都知道:css是由单独的下载线程异步下载的。

然后再说下几个现象:

这可能也是浏览器的一种优化机制。

因为你加载css的时候,可能会修改下面DOM节点的样式, 如果css加载不阻塞render树渲染的话,那么当css加载完之后, render树可能又得重新重绘或者回流了,这就造成了一些没有必要的损耗。 所以干脆就先把DOM树的结构先解析完,把可以做的工作做完,然后等你css加载完之后, 在根据最终的样式来渲染render树,这种做法性能方面确实会比较好一点。

十、事件循环进阶:macrotask与microtask

JS中分为两种任务类型:macrotaskmicrotask,在ECMAScript中,microtask称为jobs,macrotask可称为task

它们的定义?区别?简单点可以按如下理解:

分别很么样的场景会形成macrotask和microtask呢?

补充:在node环境下,process.nextTick的优先级高于Promise,也就是可以简单理解为:在宏任务结束后会先执行微任务队列中的nextTickQueue部分,然后才会执行微任务中的Promise部分。

另外,setImmediate则是规定:在下一次Event Loop(宏任务)时触发(所以它是属于优先级较高的宏任务), (Node.js文档中称,setImmediate指定的回调函数,总是排在setTimeout前面), 所以setImmediate如果嵌套的话,是需要经过多个Loop才能完成的, 而不会像process.nextTick一样没完没了。

再根据线程来理解下:

* macrotask中的事件都是放在一个事件队列中的,而这个队列由事件触发线程维护

* microtask中的所有微任务都是添加到微任务队列(Job Queues)中,等待当前macrotask执行完毕后执行,而这个队列由JS引擎线程维护 (这点由自己理解+推测得出,因为它是在主线程下无缝执行的)

所以,总结下运行机制:

* 执行一个宏任务(栈中没有就从事件队列中获取)

* 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中

* 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)

* 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染

* 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

原文链接:http://www.dailichun.com/2018/01/21/js_singlethread_eventloop.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

上一篇下一篇

猜你喜欢

热点阅读