# 浏览器渲染原理
# 事件循环
# 浏览器的进程模型
# 何为进程?
- 程序运行时需要有它自己的内存空间,可以把这块内存空间简单理解为进程
- 每个应用之间至少有一个进程 进程之间相互独立 即使要通信 也需要双方同意
# 何为线程
- 有了进程后,就可以运行代码了
- 运行代码的【人】称为线程
- 一个进程至少需要一个线程,所以进程开始会自动创建一个进程来运行代码,该线程成为主线程 主线程结束整个程序结束
- 如果程序需要同时执行多块代码 主线程就会启动更多的线程来执行代码 所以一个进程中可以包含多个线程
# 浏览器有哪些进程和线程
浏览器是一个多进程多线程的应用程序
浏览器的内部工作极其复杂
为避免相互影响,为减少连环崩溃的几率,当浏览器启动后,他会自动启动多个线程
其中最主要的进程有以下几个:
- 浏览器进程
- 网络进程
- 渲染进程
渲染进程启动后,会开启一个渲染主进程,主线程负责执行HTML css js代码
默认情况下浏览器会为每个标签页开启一个新的渲染进程,以保证不同标签页之间不相互影响
# 消息队列
当浏览器启动时会制动启动主线程和消息队列 主线程将会把消息队列中的任务依次执行,当消息队列中没有任务时主线程休眠等待下一次消息队列中有待执行的任务
# 事件循环
事件循环又叫消息循环,是浏览器渲染主线程的工作方式
在谷歌浏览器中,它会开启一个不会结束的for循环,每次循环从消队列中取出第一个任务执行,而其他线程只需要在合适的时机将任务加入到消息队列的末尾
这样依次执行消息队列的操作被称为事件循环
当浏览器启动时自动启动一个死循环,监听消息队列
# 何为异步?
在代码执行中,会遇到一些无法立即执行的任务 比如
- 计时器完成后需要执行的任务 --setTimeout/setInterval
- 网络通信完成后需要执行的任务 ==XHR/Fetch
- 用户操作后需要执行的任务 -- addEventListener
如果让渲染主线程等待这些任务的时机到达 就会导致主线程长期处于阻塞状态,从而导致浏览器卡死
渲染主线程承担着极其重要的工作,无论如何都不能阻塞!
因此浏览器选择异步来解决这个问题
计时任务执行时机到到,加入到消息队列末尾进行排队 - 使用异步的方式,使主线程永不阻塞
# js为何会阻塞页面渲染
# 任务有优先级吗?
- 主线程任务没有优先级 在任务队列中先进先出
- 但消息队列是有优先级的
- 微队列中的任务优先执行VIP 当微队列中的任务全部执行完后再执行其他队列
- 目前在谷歌浏览器中至少包含了 延时队列 交互队列 微队列
- 添加微队列的主要方式是使用Promise/MutationObserver
//立即把函数添加到微队列
Promise.resolve().then(()=>{})
setTimeout(()=>{
console.log(1)
},0)
console.log(2)
//2
//1
setTimeout(()=>{
console.log(1)
},0)
Promise.resolve().then(()=>{
console.log(2)
})
console.log(3)
//3
//2
//1
# 浏览器渲染原理
# 浏览器中什么是渲染?
渲染:将html字符串转化为屏幕上的像素点
← Javascript es6~es13 →