小结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 相关文章推荐
jQuery-onload让第一次页面加载时图片是淡入方式显示
May 23 Javascript
理解Javascript闭包
Nov 01 Javascript
Bootstrap Modal遮罩弹出层代码分享
Nov 21 Javascript
jQuery实现的分页功能示例
Jan 22 Javascript
一个简易的js图片轮播效果
Jul 22 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
Aug 16 Javascript
基于Particles.js制作超炫粒子动态背景效果(仿知乎)
Sep 13 Javascript
微信小程序wx.getImageInfo()如何获取图片信息
Jan 26 Javascript
vue无限轮播插件代码实例
May 10 Javascript
element-ui如何防止重复提交的方法步骤
Dec 09 Javascript
使用Vue+Django+Ant Design做一个留言评论模块的示例代码
Jun 01 Javascript
Angular处理未可知异常错误的方法详解
Jan 17 Javascript
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中CI操作多个数据库的代码
2012/07/05 PHP
php strnatcmp()函数的用法总结
2013/11/27 PHP
php查看请求头信息获取远程图片大小的方法分享
2013/12/25 PHP
Linux下手动编译安装PHP扩展的例子分享
2014/07/15 PHP
php判断表是否存在的方法
2015/06/18 PHP
帝国CMS留言板回复后发送EMAIL通知客户
2015/07/06 PHP
PHP中__set()实例用法和基础讲解
2019/07/23 PHP
nicejforms——美化表单不用愁
2007/02/20 Javascript
jquery 学习之二 属性相关
2010/11/23 Javascript
js substr、substring和slice使用说明小记
2011/09/15 Javascript
js查找节点的方法小结
2015/01/13 Javascript
理解javascript对象继承
2016/04/17 Javascript
js实现带农历和八字等信息的日历特效
2016/05/16 Javascript
功能强大的Bootstrap组件(结合js)
2016/08/03 Javascript
JavaScript之创意时钟项目(实例讲解)
2017/10/23 Javascript
实例详解Node.js 函数
2018/06/10 Javascript
深入浅析angular和vue还有jquery的区别
2018/08/13 jQuery
vue监听input标签的value值方法
2018/08/27 Javascript
vue+element-ui实现表格编辑的三种实现方式
2018/10/31 Javascript
Node.js实现用户评论社区功能(体验前后端开发的乐趣)
2019/05/09 Javascript
angular异步验证防抖踩坑实录
2019/12/01 Javascript
JavaScript随机数的组合问题案例分析
2020/05/16 Javascript
python通过imaplib模块读取gmail里邮件的方法
2015/05/08 Python
Python 26进制计算实现方法
2015/05/28 Python
python numpy函数中的linspace创建等差数列详解
2017/10/13 Python
uwsgi+nginx部署Django项目操作示例
2018/12/04 Python
Python创建空列表的字典2种方法详解
2020/02/13 Python
Lowe’s加拿大:家居装修、翻新和五金店
2019/12/06 全球购物
瑞士最大的图书贸易公司:Orell Füssli
2019/12/28 全球购物
Shell编程面试题
2012/05/30 面试题
自学考试自我鉴定范文
2013/09/26 职场文书
电子商务专业应届毕业生求职信
2014/06/21 职场文书
班级学习雷锋活动总结
2014/07/04 职场文书
省级三好学生主要事迹材料
2015/11/03 职场文书
情况说明书格式及范文
2019/06/24 职场文书
Mysql如何实现不存在则插入,存在则更新
2022/03/25 MySQL