理解本文需要先知道js的事件机制,可以先看这篇文章:(juejin.cn/post/752564…)
揭秘浏览器内核:多进程架构与异步机制深度解析
现代浏览器是一个复杂而高效的系统,它利用多进程架构来确保性能、稳定性和安全性。理解浏览器的内部工作原理,尤其是其多线程模型和事件循环机制,是掌握前端性能优化的关键。
浏览器多进程架构概览
以 Chrome 为代表的现代浏览器采用多进程架构,将不同的功能模块隔离在独立的进程中。这种设计带来的主要优势是:即使某个标签页崩溃(一个进程),也不会影响到整个浏览器或其他标签页(其他进程)的运行。
主要的进程包括:
- 浏览器主进程 (Browser Process): 负责用户界面(地址栏、书签等)、网络请求、文件访问以及管理其他子进程。
- 渲染进程 (Renderer Process): 通常每个 Tab 或一组 Tab 拥有一个独立的渲染进程。这是执行 JavaScript、渲染网页、处理布局和绘制的核心。
- GPU 进程 (GPU Process): 负责 3D 渲染和高性能图形处理。
- 插件进程 (Plugin Process): 管理浏览器插件(如早期的 Flash)。
JavaScript 代码执行由渲染进程负责
在这些进程中,渲染进程是网页内容的核心执行环境。渲染进程又有多个线程。
渲染进程中的五大关键线程
在渲染进程内部,有多个线程协同工作,共同完成网页的加载、渲染和脚本执行。理解这些线程的角色至关重要:
1. 渲染进程的主线程 (GUI 渲染线程)
这是渲染进程的核心线程,负责网页的渲染工作:
- 解析 HTML (生成 DOM 树)。
- 解析 CSS (生成 CSSOM 树)。
- 构建 渲染树 (Render Tree)。
- 执行 布局 (Layout) 和 绘制 (Paint) 。
2. JS 引擎线程 (如 V8引擎)
该线程负责执行 JavaScript 代码。它与 GUI 渲染线程是互斥的。
想象一下: 如果 GUI 渲染线程正在努力地根据当前的 DOM 结构绘制页面(比如计算元素位置、颜色等),而 JS 引擎线程同时也在修改这个 DOM 结构(比如添加、删除元素,改变样式),那么就会出现严重的冲突。引发大量的重排,甚至显示一个不可预测的界面。
3. 事件触发线程 (Event Trigger Thread)
这个线程负责监听用户交互事件(如点击、鼠标移动)和系统事件。当事件发生时,它会将对应的回调函数推入到事件循环的宏任务队列中。
4. 定时器触发线程 (Timer Thread)
这个线程专门处理 setTimeout 和 setInterval。浏览器会为定时器启动一个单独的线程,当设定的时间到达时,该线程会将对应的回调函数添加到宏任务队列中,等待 JS 引擎线程执行。
为什么 setTimeout 不准确?
setTimeout 回调函数并非严格按照设定时间执行,因为回调函数需要等待 JS 引擎线程空闲才能运行。即使时间到了,如果主线程正在忙于执行其他任务,回调函数也必须排队等待。
5. 异步 HTTP 请求线程 (Async HTTP Request Thread)
该线程负责处理网络请求,例如 fetch 或 XMLHttpRequest (XHR)。当请求完成(成功或失败)时,它会将对应的回调函数推入到事件循环的队列中(通常是宏任务)。