浏览器 - 事件循环 & 浏览器原理
渲染进程 - (渲染主线程)
何为异步?
代码执行过程中,会遇到一些无法立即处理的任务,比如:
● 计时完成后需要执行的 - setTimeout / setInterval
● 网络通信 - XHR / Fetch
● 用户操作后需要执行的任务 - addEventListener
如何理解JS的异步?
因为JS在浏览器中是一门单线程的语言,因为浏览器的渲染主线程只有一个
渲染主线程承载着非常多的工作 比如渲染页面 执行js代码
如果使用同步的方式就会导致主线程产生阻塞,从而导致消息队列中很多其他任务无法执行。这样一来导致主线程白白的消耗时间,另一方便导致页面无法及时更新,给用户造成卡死现象
所以浏览器采用异步的方式来避免。把计时器 / 网络 / 事件监听等这些耗时任务通过其他线程包装成任务 加入到渲染主线程的队列中 等待到它执行;
在这种异步模式下,浏览器永不阻塞,从而保证单线程的流畅运行
任务有优先级吗?
任务没有优先级 任务本质上是个消息队列 - 先进先出
但是消息队列有优先级的
不同的任务队列要分开存放
● 延时队列 - 优先级 - 中
● 交互队列 - 优先级 - 高
● 微队列 - 优先级 - 最高
JS中的计时器能做到精准计时吗?为什么?
不行,因为
1.计算机硬件没有原子钟,无法做到精准计时
2.操作系统的计时函数本身就有少量偏差,JS调用的是操作系统的 所以本质上也有偏差
3.延时任务超过5层后默认0会变成4
4.受到事件循环的影响,计时器的回调函数只能在主线程空闲的时候才会执行,因此会有偏差
单线程是异步产生的原因
事件循环是异步的实现方式
浏览器原理
浏览器是如何渲染页面的?
当浏览器的网络线程收到HTML文档后,会产生一个渲染任务,并将其转递给渲染主线程的消息队列。
在事件循环的机制下 取出渲染任务进行执行
解析HTML(prase) ->
● 生成DOM树 / CSSOM树
样式计算(Computed style) ->
● 得到计算后的样式(最终样式) - computed style
布局(Layout) ->
● 生成Layout 树(页面上展示的哪些) - 计算宽高 位置
分层(Layer) ->
● 将来某一个层改变后,仅会戳该层进行后续处理,提高效率
● transform / opacity / z-index等可能会影响分层
● 可以通过will-change更大层度影响分层结果
绘制(Paint) ->
● 为每一层生成绘制指令 - (将笔移动到10,30的位置…)类似canvas
分块(Tiling)合成线程 ->
● 分块 - 把每个图层做分块
光栅化(Raster)GPU ->
● 将每个块变成像素信息(颜色信息…)
● 优先把视窗的优先处理
画(Draw)GPU
● 生成指引信息 quad,交给GPU进程处理
● transform也是在这里完成操作的
什么是reflow?
重排 -> 修改跟几何信息相关的属性时会触发。比较影响性能 因为会导致重排 重新进行layout树。
为了避免多次操作导致布局树反复计算,浏览器会合并这些操作,当JS代码全部完成后再进行统一的计算,异步完成layout树 重排 reflow
获取几何信息属性时 会重新触发 重排reflow
什么是repaint重绘?
改变了元素的样式信息 颜色啥的会导致重绘
为什么transform效率高?
因为transform实在GPU进程进行处理的。跟主线程没关系 不会导致reflow和repaint