浏览器主要进程:
- Browser进程
- 第三方插件进程
- GPU进程
- 浏览器渲染进程
浏览器渲染进程包含的主要线程:
- GUI渲染线程:负责渲染浏览器界面,解析HTML、CSS、构建DOM树和renderObject树,布局和绘制等等;界面的重绘和回流
- JS引擎线程:JS引擎单线程。解析、运行JavaScript代码;等待并处理任务队列中的任务
- 事件触发线程:控制事件循环;当某事件触发时,该线程将对应的回调函数添加到任务队列的队尾,等待JS引擎处理
- 定时触发器线程:setInterval与setTimeout所在的进程,计时完毕后将对应的回调函数添加到任务队列中等待JS引擎线程处理;时间间隔低于4ms的时间间隔算为4ms
- 异步http请求线程:检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。
GUI渲染线程与JS引擎线程互斥:
浏览器渲染流程:
- 解析HTML构建DOM树
- 解析CSS构建render树(将CSS代码解析成树形的数据结构,然后结合DOM合并成render树)
- 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
- 绘制render树(paint),绘制页面像素信息
- 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上。
- 渲染完毕,load事件
Event Loop:
- 同步任务都在主线程上执行,形成一个
执行栈
- 主线程之外,事件触发线程管理着一个
任务队列
,只要异步任务有了运行结果,就在任务队列
之中放置一个事件 - 一旦
执行栈
中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取任务队列
,将可运行的异步任务添加到可执行栈中,开始执行。 - 宏任务与微任务
宏任务与微任务:
- 宏任务为执行中的任务
- 浏览器为了能够使得JS内部task与DOM任务能够有序的执行,会在一个task执行结束后,在下一个 task 执行开始前,对页面进行重新渲染 (
task->渲染->task->...
) - 微任务,在当前task任务后,下一个task之前,在渲染之前
- 微任务,它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染
总结下运行机制:
-
执行一个宏任务(栈中没有就从事件队列中获取)
-
执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
-
宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
-
当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
-
渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
参考资料: