浏览器的事件循环

浏览器的进程模型:

1.浏览器进程
主要负责界面显示、用户交互、子进程管理等。
2.网络进程
负责加载网络资源。内部会分为多个进程处理不同的网络任务。
3.渲染进程
启动后,开启一个渲染主线程,负责执行html,css,js文件。
默认情况下,浏览器为每一个标签页开启一个新的渲染进程,以保证不同标签之前互不影响。(chrome)
【未来有可能是一个站点一个进程】

渲染主进程的任务:

  • 解析HTML
  • 解析CSS
  • 计算样式
  • 布局
  • 处理图层
  • 每秒把页面画60次 (FPS)
  • 执行全局JS代码
  • 执行事件处理函数
  • 执行计时器的回调函数

如何调度这么多任务呢
消息队列图

  1. 渲染主进程开启一个无限循环
  2. 每次循环检查消息队列是否不为空。不为空,则取出第一个任务执行;为空,则进入休眠状态
  3. 其他所有线程可以随时向消息队列中添加任务。新任务会加到消息队列的末尾,在添加新任务时,如果主线程时休眠状态,则会将其唤醒并继续循环拿取任务

补充了解:
什么是异步?
无法立即处理的任务

  • 计时完成后需要执行的任务 —— setTimeout, setInterval
  • 网络通信完成后需要执行的任务 —— XHR,fetch
  • 用户操作后需要执行的任务 —— addEventListener

这种任务来临之后,如果让渲染主线程等待任务完成,主线程会长期处于阻塞的状态,这样连基本的页面刷新都会卡住。

此时,需要用异步执行方式代替同步,如图
异步方式执行计时器任务
计时线程开始计时后,渲染主进程即进行MQ中的下一个任务。而等计时结束后,会往MQ中添加新的任务,等待主线程执行。

这种异步模式下,浏览器不会阻塞,保证了单线程的流畅。

提问:
为某一按钮绑定事件如下,为何点击后效果是先卡住页面3秒,再变化文字

btn.onclick = function(){
	h1.textContent = "HELLO";
	delay(3000);
}

function delay(n){
	const pre = Date.now();
	while(Date.now()-pre<n){}
}

1
dom的文本更换,导致添加一个绘制任务。此任务排在MQ中等待执行,而3000ms的死循环已经开始在执行了
新增绘制任务
这个案例说明,JS会阻碍渲染。因为你执行JS,那么渲染就要滞后;你正在执行渲染,JS就要等着。

任务有优先级吗

任务本身没有优先级,在消息队列中先进先出

  • 每个任务都有一个任务类型,同一个类型的任务必须在一个队列,不同类型的任务可以在一个队列
  • 浏览器必须准备好一个微队列,微队列中的任务优先与其他所有任务的执行。

目前Chrome实现中包括但不限于这些队列,队列有对应的优先级

  • 延时队列:用于存放计时器到达后的回调任务,优先级
  • 交互队列:用于存放用户操作后产生的事件处理任务,优先级
  • 微队列:需要最快执行的任务,优先级最高

微队列中接收的主要是Promise 、MutationObserver
如图这样的队列结构,渲染主线程结束当前任务后,依次往下找优先级最高的任务载入执行,比如微队列执行完清空了再往下找最高的任务,所以有时候优先级高的会后来居上。
这样的队列结构
可以用来分析许多的面试题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值