小结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 相关文章推荐
利用javascript实现一些常用软件的下载导航
Aug 03 Javascript
javascript 浏览器检测代码精简版
Mar 04 Javascript
jquery实现不包含当前项的选择器实例
Jun 25 Javascript
javascript实现多栏闭合展开式广告位菜单效果实例
Aug 05 Javascript
js和C# 时间日期格式转换的简单实例
May 28 Javascript
jQuery插件WebUploader实现文件上传
Nov 07 Javascript
AngularJS 在同一个界面启动多个ng-app应用模块详解
Dec 20 Javascript
jquery mobile移动端幻灯片滑动切换效果
Apr 15 Javascript
vue-cli脚手架引入图片的几种方法总结
Mar 13 Javascript
小程序二次贝塞尔曲线实现购物车商品曲线飞入效果
Jan 07 Javascript
JS函数本身的作用域实例分析
Mar 16 Javascript
小程序瀑布流组件实现翻页与图片懒加载
May 19 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下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
CodeIgniter与PHP5.6的兼容问题
2015/07/16 PHP
PHP设置头信息及取得返回头信息的方法
2016/01/25 PHP
Yii2框架可逆加密简单实现方法
2017/08/25 PHP
PHP堆栈调试操作简单示例
2018/06/15 PHP
ThinkPHP5.0 图片上传生成缩略图实例代码说明
2018/06/20 PHP
详解phpstorm2020最新破解方法
2020/09/17 PHP
jquery下json数组的操作实现代码
2010/08/09 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
2013/12/17 Javascript
jquery实现select下拉框美化特效代码分享
2015/08/18 Javascript
实例讲解JavaScript中的this指向错误解决方法
2016/06/13 Javascript
JS实现焦点图轮播效果的方法详解
2016/12/19 Javascript
javascript中json对象json数组json字符串互转及取值方法
2017/04/19 Javascript
详解Node.js项目APM监控之New Relic
2017/05/12 Javascript
JavaScript实现的仿新浪微博原生态输入字数即时检查功能【兼容IE6】
2017/09/26 Javascript
浅谈vue中改elementUI默认样式引发的static与assets的区别
2018/02/03 Javascript
JS动态插入脚本和插入引用外部链接脚本的方法
2018/05/21 Javascript
「中高级前端面试」JavaScript手写代码无敌秘籍(推荐)
2019/04/08 Javascript
[01:50:49]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Aster BO3 第三场 1月24日
2021/03/11 DOTA
python 文件操作删除某行的实例
2017/09/04 Python
windows下添加Python环境变量的方法汇总
2018/05/14 Python
Python使用爬虫抓取美女图片并保存到本地的方法【测试可用】
2018/08/30 Python
详解Python 定时框架 Apscheduler原理及安装过程
2019/06/14 Python
python双端队列原理、实现与使用方法分析
2019/11/27 Python
HTML高亮关键字的实现代码
2018/10/22 HTML / CSS
英国百年闻名的优质健康产品连锁店:Holland & Barrett
2019/12/19 全球购物
毕业生就业自荐信
2013/12/04 职场文书
优秀员工评语
2014/02/10 职场文书
教师正风肃纪剖析材料
2014/10/20 职场文书
2014年双拥工作总结
2014/11/21 职场文书
公司总经理岗位职责
2015/04/01 职场文书
2015年人力资源工作总结
2015/04/08 职场文书
小学班主任研修日志
2015/11/13 职场文书
2016道德模范先进事迹材料
2016/02/26 职场文书
Python MNIST手写体识别详解与试练
2021/11/07 Python
Java实现HTML转为Word的示例代码
2022/06/28 Java/Android