chrome浏览器的事件循环你现在还不会吗?

360 阅读4分钟

首先先了解一下什么是进程和线程

进程图.png

进程

进程简单来说就是,QQ,微信,王者荣耀三个软件,他们都会有独立的进程,有了进程之后就可以开始干活了,并且进程之间是互不干扰的,不会因为QQ崩溃了而导致微信无法使用,如果想要通信,需要双方同意才可以传递数据

线程

线程就好比,你的老板开了一家公司,把你招聘进来干活,那么老板就是进程,而你就是线程。每个进程都至少要有一个线程,不然的话没人干活呀,所以每次开辟一个进程都会自动生成一个对应的线程。如果程序比较多,比较复杂,进程也可以开辟多个线程同时执行代码

举个例子

线程图.png

  1. 你进入王者荣耀就会开辟一个内存空间,生成一个进程
  2. 进程会生成多个线程完成不同的工作
  3. 主线程负责一些比较复杂的逻辑,控制游戏逻辑和渲染
  4. 游戏线程比如移动方向,释放技能的一些监听
  5. 网络线程,你放技能,移动,双方都是同步看到的,这些就是网络线程去完成的

那么浏览器里面有什么进程和线程呢?

浏览器进程.png

1. 浏览器进程

主要负责界⾯显示、⽤户交互、⼦进程管理等。浏览器进程内部会启动多个线程处理不同的任务。

2. ⽹络进程

负责加载⽹络资源。⽹络进程内部会启动多个线程来处理不同的⽹络任务。

3. 渲染进程

渲染进程启动后,会开启⼀个渲染主线程,主线程负责执⾏ HTML、CSS、JS 代码。默认情况下,浏览器会为每个标签⻚开启⼀个新的渲染进程,以保证不同的标签⻚之间不相互影响。

渲染主线程是怎么工作的呢?

渲染主线程就是浏览器中最重要且最繁忙的线程

  • 渲染html
  • 解析css
  • 解析js
  • 计算样式
  • 布局
  • 执行事件处理函数
  • . . . . . .

浏览器渲染流程详解juejin.cn/post/722551…

负责处理这么多任务,还出现了一个难题如何调度任务?

  1. 当浏览器在执行js代码的时候,用户点击了按钮,那么是继续执行js代码还是执行点击后的逻辑?
  2. 当计时器时间到了,恰巧用户又点了一下按钮,那么先执行定时器还是点击后的逻辑呢?

event loop (事件循环)

事件循环.png

  1. 渲染主线程会开启一个无限循环,每次取出消息队列中第一个任务执行,直到消息队列为空
  2. 当有其他任务(定时器的回调,点击事件的函数)则追加到消息队列的末尾,依次执行

什么是异步呢?

我们平时在写代码中也会经常接触到一些无法立即执行的任务

  1. 定时器 (setTimeout, setInterval
  2. 网络请求ajax (XHR, Fetch
  3. 绑定点击事件 (onclick, addEventListener

因为js是一门单线程语言,如果渲染主线程等这些代码执行完再执行下一个任务,渲染主线程长期阻塞,将会导致整个页面卡死,用户体验极差

无法立即执行代码浏览器如何处理的?

异步执行.png

  1. 浏览器使用了异步来解决这个问题
  2. 当执行js时,渲染主线程遇到了一个定时器,那么会交给一个计时线程,当时间到了,会生成一个任务,追加到消息队列的末尾,等待渲染主线程的调用,如果有多个异步代码,也是使用相同的步骤去执行
  3. 使⽤异步的⽅式,渲染主线程永不阻塞

那么异步任务有优先级吗?

  1. 任务是没有优先级的,在消息队列中先进先出
  2. 但消息队列中是有优先级的
  3. 在chrome中至少包含以下队列
  • 延时队列:⽤于存放计时器到达后的回调任务,优先级「中」
  • 交互队列:⽤于存放⽤户操作后产⽣的事件处理任务,优先级「⾼」
  • 微队列:⽤户存放需要最快执⾏的任务,优先级「最⾼」

微队列

// 立即把回调函数添加到微队列中
Promise.resolve.then(回调函数)

交互队列

跟用户交互的事件就会进入交互队列

  • 鼠标点击事件
  • 键盘事件
  • 窗口大小改变
  • . . . . . .

延迟队列

  • setTimeout
  • setInterval