一、浏览器进程
浏览器多进程架构,每一个页卡都是一个进程。
1. 渲染进程
渲染进程包含多个子线程。
- GUI渲染线程和JS引擎线程是互斥的,一个执行,另一个就要挂起等待。
- 事件触发线程
Event Loop是一个独立的线程。 - 事件
click、setTimeout、ajax也是一个独立线程。
2. 浏览器EventLoop
二、Node的事件环
- 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个阶段就去执行全部微任务,接下来再拿出一个宏任务。
poll阶段
- 检测
poll队列是否为空,如果不为空则执行队列中的任务。直到超时或者全部执行完毕。 - 执行完毕后检测
setImmediate队列是否为空,如果不为空则执行check阶段,如果为空则等待时间到达。时间到达后回到timer阶段。 - 等到时间到达时可能会出现新的
callback,此时也在当前阶段被清空。