小结Node.js中非阻塞IO和事件循环


Posted in Javascript onSeptember 18, 2014

学习和使用Node.js已经有两个月,使用express结合mongoose写了一个web应用和一套RESTful web api,回过头来看Node.js官网首页对Node.js的介绍:Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.那么其中的non-blocking I/O model 意味着什么呢?

非阻塞的IO模型

首先,IO操作无疑是耗时的,当服务器端接收到大量请求时,为每一个请求创建进程或线程的同时,也增加了额外的内存开销,也可能浪费更多的时间资源。

由于Node.js是事件驱动的,于是它使用了事件循环来解决IO操作带来的瓶颈问题。在Node.js中,一个IO操作通常会带有一个回调函数,当IO操作完成并返回时,就会调用这个回调函数,而主线程则继续执行接下来的代码。简单的用一个例子来说明这个问题:

request('http://www.google.com', function(error, response, body) {
   console.log(body);
});
 
console.log('Done!');

这段代码的意思是向'http://www.google.com'发出请求,当请求返回这则调用回调函数输出响应信息。由于Node.js的运行机制,这段代码运行后,会立即在控制台输出'Done!',然后一段时间后再输出响应的信息。

事件循环 event loop

接下来,来讨论下事件循环的机制。首先说说调用?C,比如有如下一段代码:

function A(arg, func){
  var a = arg;
 
  func();
  console.log('A');  
}
 
function B(){
  console.log('B');
}
 
A(0, B);

当代码执行后,函数A首先被推入调用?C中成为栈顶元素并开始执行A,在执行过程中函数B又被推入调用?C成为栈顶元素,在B执行完成后,B被弹出调用?C,A再次成为栈顶元素,在A执行完成后A被弹出调用?C,调用?C呈空闲状态。

在Javascript运行时中存在一个消息队列,而消息和一个回调函数相关联,当一个事件被触发时,如果这个事件有相应的回调函数,则该消息就会被加入到消息队列中去。

回过头来说事件循环到底循环的是什么,在代码开始执行后,函数被不断推入调用?C中,就拿上面的例子来讲,request被推入调用?C中,这个函数将进行一个http请求(这个http请求将交由Node.js的底层模块来实现)同时请求完成的事件和一个回调函数关联起来,request被弹出调用?C,console.log被推入调用?C开始执行。当请求完成时,完成事件被触发,一条消息被添加进消息队列中,消息队列首先会检查调用?C是否为空闲状态,如果调用?C并不空闲,则会一直等待到调用?C空闲状态后,将消息队列的头部弹出,此时与该消息相关联的回调函数被执行。

小结

以上就无阻塞模型和事件循环在概念上进行了总结。而这个事件循环的机制并不仅仅是Node.js所独有的,并且Node.js的代码是单线程执行的,在面对大量并发请求的时候,又有着什么优势呢?

小结Node.js中非阻塞IO和事件循环

上面这张图展示了Node.js的架构图,Node.js的底层有一个模块负责维护线程池,当一个IO请求发出的时候,Node.js的底层模块将新建一个线程来处理请求,完成后再将结果交还给上层。那么,当有多个请求的时候,Node.js的底层模块将利用尽可能少的线程来完成最多的任务,如果存在空闲的线程,它将继续被利用来做其他的事情,这对于前面说的针对每个请求开一个新的进程或线程而言,无疑“聪明”许多,也更加高效了。

这篇文章是对学习Node.js的一个总结,其中若有问题和不足,欢迎批评指正。

Javascript 相关文章推荐
document.onreadystatechange事件的用法分析
Oct 17 Javascript
JS打开新窗口的2种方式
Apr 18 Javascript
从数据结构的角度分析 for each in 比 for in 快的多
Jul 07 Javascript
jquery日历控件实现方法分享
Mar 07 Javascript
使用jQuery不判断浏览器高度解决iframe自适应高度问题
Dec 16 Javascript
JavaScript实现找质数代码分享
Mar 24 Javascript
JavaScript 是什么意思
Sep 22 Javascript
详解Angular.js指令中scope类型的几种特殊情况
Feb 21 Javascript
深入理解React中何时使用箭头函数
Aug 23 Javascript
微信小程序使用scroll-view标签实现自动滑动到底部功能的实例代码
Nov 09 Javascript
vue中tab选项卡的实现思路
Nov 25 Javascript
详解vue3中组件的非兼容变更
Mar 03 Vue.js
JavaScript将取代AppleScript?
Sep 18 #Javascript
Javascript MVC框架Backbone.js详解
Sep 18 #Javascript
JS回调函数的应用简单实例
Sep 17 #Javascript
js实现在同一窗口浏览图片
Sep 17 #Javascript
js实现获取焦点后光标在字符串后
Sep 17 #Javascript
在JavaScript中构建ArrayList示例代码
Sep 17 #Javascript
取得元素的左和上偏移量的方法
Sep 17 #Javascript
You might like
php文件系统处理方法小结
2016/05/23 PHP
浅谈PHP的数据库接口和技术
2016/12/09 PHP
Thinkphp5结合layer弹窗定制操作结果页面
2017/07/07 PHP
HR vs CL BO3 第二场 2.13
2021/03/10 DOTA
JS控件autocomplete 0.11演示及下载 1月5日已更新
2007/01/09 Javascript
用javascript实现给出的盒子的序列是否可连为一矩型
2007/08/30 Javascript
js 弹出框只弹一次(二次修改之后的)
2013/11/26 Javascript
js利用数组length属性清空和截短数组的小例子
2014/01/15 Javascript
jquery实现将获取的颜色值转换为十六进制形式的方法
2014/12/20 Javascript
js支持键盘控制的左右切换立体式图片轮播效果代码分享
2015/08/26 Javascript
JavaScript实现倒计时代码段Item1(非常实用)
2015/11/03 Javascript
JS 全屏和退出全屏详解及实例代码
2016/11/07 Javascript
Angular 2.x学习教程之结构指令详解
2017/05/25 Javascript
Vue下的国际化处理方法
2017/12/18 Javascript
解决nodejs的npm命令无反应的问题
2018/05/17 NodeJs
vue element项目引入icon图标的方法
2018/06/06 Javascript
thinkjs微信中控之微信鉴权登陆的实现代码
2019/08/08 Javascript
js设计模式之单例模式原理与用法详解
2019/08/15 Javascript
解决Layui数据表格显示无数据提示的问题
2019/11/14 Javascript
一篇文章看懂JavaScript中的回调
2021/01/05 Javascript
Python中处理时间的几种方法小结
2015/04/09 Python
Python中的字符串查找操作方法总结
2016/06/27 Python
python+POP3实现批量下载邮件附件
2018/06/19 Python
python石头剪刀布小游戏(三局两胜制)
2021/01/20 Python
Python使用plt.boxplot() 参数绘制箱线图
2020/06/04 Python
Python创建文件夹与文件的快捷方法
2020/12/08 Python
Europcar意大利:汽车租赁
2019/07/07 全球购物
anello泰国官方网站:日本流行包包品牌
2019/08/08 全球购物
用Python匹配HTML tag的时候,<.*>和<.*?>有什么区别
2012/11/04 面试题
初中同学会活动方案
2014/08/22 职场文书
焦裕禄精神心得体会
2014/09/02 职场文书
新学期红领巾广播稿
2014/10/04 职场文书
2016年度先进班组事迹材料
2016/03/01 职场文书
女人创业励志语录,句句蕴含能量,激发你的潜能
2019/08/20 职场文书
解决Maven项目中 Invalid bound statement 无效的绑定问题
2021/06/15 Java/Android
Vscode中SSH插件如何远程连接Linux
2022/05/02 Servers