小结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 相关文章推荐
驱动事件的addEvent.js代码
Mar 27 Javascript
jquery插件如何使用 jQuery操作Cookie插件使用介绍
Dec 15 Javascript
js拦截alert对话框另类应用
Jan 16 Javascript
微信小程序开发之选项卡(窗口底部TabBar)页面切换
Apr 12 Javascript
jQuery用户头像裁剪插件cropbox.js使用详解
Jun 07 jQuery
基于vue-ssr服务端渲染入门详解
Jan 08 Javascript
使用ngrok+express解决本地环境中微信接口调试问题
Feb 26 Javascript
浅谈node中的cluster集群
Jun 02 Javascript
jQuery实现轮播图及其原理详解
Apr 12 jQuery
微信小程序之onLaunch与onload异步问题详解
Mar 28 Javascript
React Native中ScrollView组件轮播图与ListView渲染列表组件用法实例分析
Jan 06 Javascript
vue 虚拟DOM的原理
Oct 03 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
在Win7 中为php扩展配置Xcache
2014/10/08 PHP
PHP设计模式之适配器模式原理与用法分析
2018/04/25 PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
2020/02/21 PHP
JavaScript中使用concat()方法拼接字符串的教程
2015/06/06 Javascript
CSS javascript 结合实现悬浮固定菜单效果
2015/08/23 Javascript
基于jQuery实现的双11天猫拆红包抽奖效果
2015/12/01 Javascript
基于javascript html5实现多文件上传
2016/03/03 Javascript
JS获取子窗口中返回的数据实现方法
2016/05/28 Javascript
Vue.js学习示例分享
2017/02/05 Javascript
微信小程序实战之自定义模态弹窗(8)
2017/04/18 Javascript
jQuery操作之效果详解
2017/05/19 jQuery
详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)
2017/08/30 Javascript
利用pm2部署多个node.js项目的配置教程
2017/10/22 Javascript
spirngmvc js传递复杂json参数到controller的实例
2018/03/29 Javascript
axios向后台传递数组作为参数的方法
2018/08/11 Javascript
Jquery实现无缝向上循环滚动列表的特效
2019/02/13 jQuery
JQuery中DOM节点的操作与访问方法实例分析
2019/12/23 jQuery
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
python中pandas.DataFrame对行与列求和及添加新行与列示例
2017/03/12 Python
python数字图像处理实现直方图与均衡化
2018/05/04 Python
使用Python写一个量化股票提醒系统
2018/08/22 Python
python如何把字符串类型list转换成list
2020/02/18 Python
python 实现围棋游戏(纯tkinter gui)
2020/11/13 Python
Java面试题:为什么要用Java
2012/05/11 面试题
一名老师的自我评价
2014/02/07 职场文书
护理助产毕业生的求职信
2014/03/02 职场文书
绿色学校实施方案
2014/03/31 职场文书
企业诚信承诺书
2014/05/23 职场文书
竞选班长演讲稿500字
2014/08/22 职场文书
解放思想演讲稿
2014/09/11 职场文书
2014年酒店服务员工作总结
2014/12/08 职场文书
社区党支部公开承诺书
2015/04/29 职场文书
《游戏公平》教学反思
2016/02/20 职场文书
2019大学竞选班长发言稿
2019/06/27 职场文书
七年级作文之环保作文
2019/10/17 职场文书
「玫瑰之王的葬礼」舞台剧主视觉图公开
2022/03/21 日漫