浏览器事件环、node事件循环机制

881 阅读2分钟

一、浏览器进程


浏览器多进程架构,每一个页卡都是一个进程。

image.png

1. 渲染进程

渲染进程包含多个子线程。

  • GUI渲染线程和JS引擎线程是互斥的,一个执行,另一个就要挂起等待。
  • 事件触发线程Event Loop是一个独立的线程。
  • 事件click、setTimeout、ajax也是一个独立线程。

2. 浏览器EventLoop

image.png

二、Node的事件环

image.png

  • V8引擎解析JS脚本
  • 解析后的代码,如果调用了Node API,则Node会交给 libuv 库来处理。
  • libuv库负责Node API的执行,它将不同的任务分配给不同的线程,形成一个Event Loop,以异步的方式将任务的执行结果返回给V8引擎。
  • V8引擎再将结果返回给用户。
本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。
   ┌───────────────────────────┐
┌─>│           timers          │ 
│  └─────────────┬─────────────┘
|   执行延迟到下一个循环迭代的 I/O 回调。
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
|   仅系统内部使用。
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      
|  检索新的I/O事件;执行与 I/O相关的回调  ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  setImmediate() 回调函数在这里执行。  └───────────────┘
│  ┌─────────────┴─────────────┐      
│  │           check           │
│  └─────────────┬─────────────┘
|  一些关闭的回调函数
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

Event Loop执行的每个阶段,都对应一个任务队列。

新版node(11+)的Event Loop要和老版表现一致。
旧版是每个宏任务阶段队列全部执行完成后执行一遍微任务.新版是拿出一个宏任务,完成6个阶段就去执行全部微任务,接下来再拿出一个宏任务。

image.png

poll阶段
  • 检测poll队列是否为空,如果不为空则执行队列中的任务。直到超时或者全部执行完毕。
  • 执行完毕后检测setImmediate队列是否为空,如果不为空则执行check阶段,如果为空则等待时间到达。时间到达后回到timer阶段。
  • 等到时间到达时可能会出现新的callback,此时也在当前阶段被清空。