浏览器与 Node 的事件循环
本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
简介:
浏览器和Node.js的事件循环是异步操作的核心机制。它们通过管理任务队列和回调函数,确保程序在处理耗时任务时不会阻塞主线程,从而实现高效、响应式的应用开发。
- 浏览器中的事件循环
- 执行栈(Call Stack)
- 任务队列(Task Queue)
- 渲染(Render)
- 浏览器通常会在一个宏任务执行完毕后,且在执行下一个宏任务之前进行渲染。不过,这也不是绝对的,浏览器会根据自身的优化策略和任务的紧急程度等来决定是否进行渲染。例如,在一个复杂的动画场景中,浏览器可能会更频繁地进行渲染以保证动画的流畅性。
- Node.js中的事件循环
- 阶段(Phases)
- Node.js的事件循环分为6个阶段,分别是
timers
、pending callbacks
、idle, prepare
、poll
、check
、close callbacks
。
- timers阶段:这个阶段会执行
setTimeout
和setInterval
的回调函数。需要注意的是,这些回调函数的执行时机并不是严格按照设置的时间来的,而是在进入timers
阶段且满足时间条件时才会执行。例如,如果在setTimeout
回调函数之前有一个长时间运行的同步操作,那么setTimeout
回调函数可能会延迟执行。
- pending callbacks阶段:处理一些系统操作(如TCP错误回调等)的回调函数,这些回调函数在之前的轮询中可能没有被处理完。
- idle, prepare阶段:这是内部使用的阶段,主要用于一些准备工作。
- poll阶段:这是一个比较复杂的阶段。它主要有两个功能。一是等待新的I/O事件;二是在适当的时候执行与I/O相关的回调函数。如果没有新的I/O事件,它会检查
timers
阶段是否有到期的定时器,如果有就会回到timers
阶段执行定时器的回调函数。
- check阶段:主要用于执行
setImmediate
的回调函数。setImmediate
是Node.js特有的一个函数,它的回调函数会在check
阶段执行。
- close callbacks阶段:用于执行
close
事件的回调函数,比如socket.on('close', callback)
中的callback
函数。
- Node.js与浏览器事件循环的区别
- 任务类型的差异:Node.js有自己独特的任务阶段划分,如
setImmediate
和process.nextTick
。process.nextTick
是一个特殊的微任务,它会在当前操作完成后立即执行,甚至优先于其他微任务。而浏览器没有setImmediate
和process.nextTick
这些概念。
- I/O处理的重点不同:Node.js更侧重于服务器端的I/O处理,事件循环的设计也更注重高效处理大量的I/O请求。例如,在Node.js的
poll
阶段,对I/O事件的等待和处理是核心功能之一。而浏览器的事件循环主要是为了处理用户交互、页面渲染以及网络请求等浏览器相关的任务。