事件循环系统

54 阅读2分钟

事件循环系统

每个渲染进程都有一个主线程

  • 主线程非常繁忙
  1. 要处理 DOM
  2. 要计算样式
  3. 要处理布局
  4. 同时还需要处理 JavaScript 任务
  5. 各种输入事件
  • 要让这么多不同类型的任务在主线程中有条不紊地执行,这就需要一个系统来统筹调度这些任务,这个统筹调度系统就是消息队列和事件循环系统。

单线程处理任务

  • 我们先从最简单的场景讲起,比如有如下一系列的任务:
void MainThread(){
     int num1 = 1+2; // 任务 1
     int num2 = 20/5; // 任务 2
     int num3 = 7*8; // 任务 3
     print(" 最终计算的值为:%d,%d,%d",num,num2,num3); // 任务 4 
  }
  • 任务 1:1+2
  • 任务 2:20/5
  • 任务 3:7*8
  • 任务 4:打印出任务 1、任务 2、任务 3 的运算结果
  • image.png 我们把所有任务代码按照顺序写进主线程里,等线程执行时,这些任务会按照顺序在线程中依次被执行;等所有任务执行完成之后,线程会自动退出。

在线程运行过程中处理新任务

  • 例如:
  1. 在执行一个JS函数,执行到一半的时候,用户点击了按钮,我们需要立即去执行点击事件的回调函数嘛?
  2. 再比如,正在执行一个js函数,执行到一半的时候,某个定时器到达了时间,应该立即去执行它的回调吗?
  • 排队等待 ⇒ 在哪儿排队呢? =⇒ 消息队列(任务队列)

消息队列

  • 消息队列是一种数据结构,可以存放要执行的任务。它符合队列“先进先出”的特点,也就是说要添加任务的话,添加到队列的尾部;要取出任务的话,从队列头部去取。
  • image.png
  • 有了队列之后,我们就可以继续改造线程模型了
  1. 添加一个消息队列;
  2. IO 线程中产生的新任务添加进消息队列尾部;
  3. 渲染主线程会循环地从消息队列头部中读取任务,执行任务
  • image.png
  • image.png
  • 当主线程同步任务执行完之后,会不断的循环去消息队列中查看是否有新的任务可以执行,有就拿来执行

跨进程发送消息

  • 渲染进程专门有一个 IO 线程用来接收其他进程传进来的消息,接收到消息之后,会将这些消息组装成任务发送给渲染主线程。当然,是先在消息队列中排队。
  • image.png
  • image.png