Skip to content

执行机制 - Node与浏览器Event Loop的差异 #37

@logan70

Description

@logan70

Node与浏览器Event Loop的差异

Node.js 运行机制

Node.js运行机制

Node.js采用V8作为JS的解析引擎,而I/O处理方面使用了自己设计的libuv,libuv是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的API,Node.js内的事件循环机制也由其实现。

Node.js运行机制简化如下:

  1. V8引擎将JavaScript代码解析为机器码。
  2. 解析后的代码,调用Node API。
  3. libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
  4. V8引擎再将结果返回给用户。

Node.js 事件循环

Node.js内的事件循环机制由libuv实现,分6个阶段反复进行。

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘
  • timers 阶段:这个阶段执行timer(setTimeout、setInterval)的回调
  • I/O callbacks 阶段:处理一些上一轮循环中的少数未执行的 I/O 回调
  • idle, prepare 阶段:仅node内部使用
  • poll 阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里
  • check 阶段:执行 setImmediate() 的回调
  • close callbacks 阶段:执行 socket 的 close 事件回调

Node.js中也存在微任务队列,包括process.nextTickpromises等。

需要注意的两点:

  • process.nextTick优先级高于promises
  • 事件循环每个阶段之间都会检查微任务队列并执行。

Node与浏览器Event Loop的差异

  • Node.js内,microtask 在事件循环的各个阶段之间执行;浏览器端,microtask 在事件循环的 macrotask 执行完之后执行。
  • Node 10及之前版本,timers阶段若有多个定时器回调,则全部执行之后再去检查微任务队列;而Node11及之后版本,则是执行一个宏任务就去检查微任务队列,跟浏览器端表现趋于一致。
setTimeout(()=>{
  console.log('timer1')
  Promise.resolve().then(() => console.log('promise1'))
}, 0)
setTimeout(()=>{
  console.log('timer2')
  Promise.resolve().then(() => console.log('promise2'))
}, 0)

Node 10及之前版本打印顺序:timer1,timer2,promise1,promise2

Node 11及之后版本打印顺序:timer1,promise1,timer2,promise2

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions