概述
不论在浏览器环境,还是Node环境,js运行的事件循环都是重中之重,但两个环境下的事件循环是基于不同的原理,尤其是Node.js 10+版本之前,一个是基于浏览器,一个是基于 libuv 库。
V8引擎本身并没有异步运行的能力,而是借助浏览器的其他线程实现的,而在 Node.js 中,异步实现主要依赖于 libuv。
事件循环
事件循环是一个无限while-true循环。
六个阶段
事件循环分为六个阶段:
- timers:执行setTimout和setInterval的回调函数;
- pending callbacks :执行某些系统操作(如 TCP 错误类型)的回调函数;
- prepare: 系统内部使用;
- poll: 执行与 I/O 相关的回调,Node可能在这个阶段阻塞。所有的事件循环以及回调处理都在这执行;
- check:setImmediate() 回调在这执行。setImmediate 并不是立马执行,而是当 poll 中没有新的事件处理时就执行该部分;
发起事件循环
当 Node.js 启动后,会初始化事件循环,处理已提供的输入脚本,它可能会先调用一些异步的 API、调度定时器,或者 process.nextTick(),然后再开始处理事件循环。
所以,Node.js 事件循环的发起点有 4 个:
- Node.js 启动后;
- setTimeout 回调函数;
- setInterval 回调函数;
- 也可能是一次 I/O 后的回调函数。