小结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 相关文章推荐
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
Mar 10 Javascript
jQuery实现漂亮实用的商品图片tips提示框效果(无图片箭头+阴影)
Apr 16 Javascript
原生JS简单实现ajax的方法示例
Nov 29 Javascript
jQuery实现页面滚动时智能浮动定位
Jan 08 Javascript
js 作用域和变量详解
Feb 16 Javascript
基于iScroll实现下拉刷新和上滑加载效果
Jul 18 Javascript
js登录滑动验证的实现(不滑动无法登陆)
Jan 03 Javascript
vue+webpack实现异步组件加载的方法
Feb 03 Javascript
利用angular、react和vue实现相同的面试题组件
Feb 19 Javascript
layui表格内容溢出的解决方法
Sep 06 Javascript
你知道JavaScript Symbol类型怎么用吗
Jan 08 Javascript
vue如何在用户要关闭当前网页时弹出提示的实现
May 31 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新手上路(十一)
2006/10/09 PHP
php中jQuery插件autocomplate的简单使用笔记
2012/06/14 PHP
解析:通过php socket并借助telnet实现简单的聊天程序
2013/06/18 PHP
linux实现php定时执行cron任务详解
2013/12/24 PHP
浅谈json_encode用法
2015/03/05 PHP
解析PHP的Yii框架中cookie和session功能的相关操作
2016/03/17 PHP
AngularJS初始化静态模板详解
2016/01/14 Javascript
jQuery动态添加可拖动元素完整实例(附demo源码下载)
2016/06/21 Javascript
js中window.open的参数及注意注意事项
2016/07/06 Javascript
jQuery实现的自动加载页面功能示例
2016/09/04 Javascript
JavaScript学习笔记整理_简单实现枚举类型,扑克牌应用
2016/09/19 Javascript
前端开发之CSS原理详解
2017/03/11 Javascript
vue移动UI框架滑动加载数据的方法
2018/03/12 Javascript
AngularJS实现与后台服务器进行交互的示例讲解
2018/08/13 Javascript
在vue项目中引用Iview的方法
2018/09/14 Javascript
基于原生js实现判断元素是否有指定class名
2020/07/11 Javascript
[03:09]DOTA2亚洲邀请赛 LGD战队出场宣传片
2015/02/07 DOTA
python list语法学习(带例子)
2013/11/01 Python
python命令行参数sys.argv使用示例
2014/01/28 Python
python实现颜色空间转换程序(Tkinter)
2015/12/31 Python
python中子类调用父类函数的方法示例
2017/08/18 Python
python音频处理用到的操作的示例代码
2017/10/27 Python
Python基于win32ui模块创建弹出式菜单示例
2018/05/09 Python
python2.7实现邮件发送功能
2018/12/12 Python
在python中获取div的文本内容并和想定结果进行对比详解
2019/01/02 Python
Form表单及django的form表单的补充
2019/07/25 Python
Python 函数用法简单示例【定义、参数、返回值、函数嵌套】
2019/09/20 Python
Python批量处理csv并保存过程解析
2020/05/16 Python
马克华菲官方商城:Mark Fairwhale
2016/09/04 全球购物
Servlet的实例是在生命周期什么时候创建的?配置servlet最重要的是什么?
2012/05/30 面试题
如何写毕业求职自荐信
2013/11/06 职场文书
学生党员一帮一活动总结
2014/07/08 职场文书
水利水电专业自荐信
2014/07/08 职场文书
专家推荐信范文
2015/03/26 职场文书
村党总支部公开承诺书2016
2016/03/25 职场文书
Python快速实现一键抠图功能的全过程
2021/06/29 Python