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

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

相关推荐
莹雨潇潇7 分钟前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
Jiaberrr15 分钟前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
Tiffany_Ho1 小时前
【TypeScript】知识点梳理(三)
前端·typescript
安冬的码畜日常2 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
太阳花ˉ2 小时前
html+css+js实现step进度条效果
javascript·css·html
小白学习日记3 小时前
【复习】HTML常用标签<table>
前端·html
john_hjy3 小时前
11. 异步编程
运维·服务器·javascript
风清扬_jd3 小时前
Chromium 中JavaScript Fetch API接口c++代码实现(二)
javascript·c++·chrome
丁总学Java3 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js