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

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

相关推荐
崔庆才丨静觅18 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606118 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了18 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅19 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅19 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅19 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment19 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅20 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊20 小时前
jwt介绍
前端
爱敲代码的小鱼20 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax