node运行机制&事件循环

node非阻塞模型

node运行机制的核心可以概括为非阻塞 ,我们都知道javascript是单线程的,不单单是指在浏览器环境中,在node环境中同样如此。

注:这里明确js的单线程的含义------在浏览器环境中,一个tab页对应一个renderer渲染进程,这个进程又包括了如GUI渲染线程、js引擎线程、计时器线程等多个线程,所以对于浏览器来说,js代码是由一个js引擎线程来执行的,即js是单线程的;在node环境下,一个node应用对应了一个进程,这个进程下负责执行js代码的也只有一个线程,即node环境下js也是单线程的。

简单举个单线程阻塞的例子:

javascript 复制代码
function a() {
    console.log('执行a函数');
}
function b() {
    while(true) {} // 无限循环阻塞了整个js执行线程的继续执行,a函数永远得不到执行
    a();
}
b();

node环境中的js之所以可以应对高并发的耗时操作(比如请求响应、数据库操作、IO)主要就归功于node的非阻塞机制

所谓非阻塞运行机制,概括来说就是将高耗时的操作"移出"js主线程(做异步处理,即交给异步模块处理),这样也就做到了不阻塞js主线程不断向下处理逻辑。 而那些高耗时的操作(相对于js主线程)后台执行,他们被异步模块所处理,异步模块又是多线程的,换句话说还是多线程处理高并发。

当js主线程的调用栈清空时,后台处理的异步操作按照一定的优先级顺序加入js主线程的调用栈来执行。这个优先级顺序不同于浏览器环境下的事件循环规则,而是node事件循环。

事件循环说白了就是js代码执行的一种机制,这种执行机制叫做"事件循环"。

node事件循环

简单回顾一下浏览器环境中的事件循环是什么样子的,如下demo:

javascript 复制代码
setTimeout(() => {
    console.log('callback');
}, 1000)
​
console.log("begin");
  1. 首先整个Task入栈(被js主线程执行),遇到setTimeout,将其交给异步模块处理(计时器线程)。
  1. 此时js主线程继续执行输出了begin,与js主线程并行的还有计时器线程中的计时任务,直至1s后,计时器线程将setTimeout的回调函数推入"宏任务队列"中去。
  2. js引擎线程(主线程)从宏任务队列中取出队头回调,输出callback

上面我们提到了"宏任务队列",当然还有"微任务队列",两者收集不同的回调并在不同时机执行,这里不多赘述。node事件循环与浏览器事件循环做对比,其实就两点差异:

  • 宏任务队列一分为三:Timer队列、Poll队列、Check队列,宏任务队列的本质不变,都是在js引擎线程空时从队列中取出新的回调入栈执行,只是说这三者对异步操作进行了更细的分类,分别收集不同异步操作的回调。

    Timer队列 :收集setTimeoutsetInterval这两个计时器的回调任务

    Poll队列 :收集文件IO数据库操作网络请求等耗时操作的回调(出队优先级高于其它两个队列

    Check队列 :收集setImmediate(node环境特有的api,也就是把回调立即加入队列)的回调。

  • 在微任务队列之前增加nextTick队列,收集process.nextTick的回调函数。

    (从宏任务队列中取出新的回调入栈执行的过程叫做一次TicknextTick就是在下一次Tick之前执行)

如上示意图,js调用栈空时接着执行nextTick队列中的任务(入栈执行),再者是微任务,最后在事件循环队列中取出下一个回调执行。

demo

javascript 复制代码
console.log('同步代码');
​
process.nextTick(() => {
    console.log('tick');
});
​
Promise.resolve().then(() => {
    console.log('promise');
});
​
setImmediate(() => {
    console.log('setImmediate');
})
​
// 同步代码 tick promise setImmediate

除了第一行直接输出之外,其它的都是异步任务,进入对应的队列,然后按顺序执行。

相关推荐
JiaWen技术圈13 分钟前
主流非 JWT 式 Access Token 方案
前端·安全
ZC跨境爬虫33 分钟前
跟着 MDN 学 HTML day_57:(HTML 表格进阶特性与无障碍实践)
java·前端·javascript·ui·html·音视频
Moment34 分钟前
刷 Reddit 1 小时没结果?我用这个方法 10 秒挖出真实需求
前端·javascript·后端
折翅嘀皇虫35 分钟前
【无标题】steal_work_thread_pool
服务器·前端·算法
w_t_y_y37 分钟前
VUE组件配置项(零)概述
前端·javascript·vue.js
水云桐程序员39 分钟前
Web应用的分类
前端·javascript·vue.js·react.js·webkit
Jack N39 分钟前
2026 Web 网站性能优化指南
前端·性能优化
yqcoder39 分钟前
TypeScript 进阶:如何精准获取对象的所有 Key?
javascript·ubuntu·typescript
UXbot40 分钟前
支持移动端原型绘制的 AI 工具核心功能对比(2026):5 款主流平台能力横向评测
前端·低代码·ui·交互·原型模式·web app
ZC跨境爬虫1 小时前
跟着 MDN 学 HTML day_54:(深入掌握 XSLTProcessor API)
前端·javascript·ui·html·媒体