深入浅析Node.js 事件循环


Posted in Javascript onDecember 20, 2015

Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。

(来源于Javascript是单线程又是异步的,但是这种语言有个共同的特点:它们是 event-driven 的。驱动它们的 event 来自一个异构的平台。)

Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。

Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。

Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.

事件驱动模型

Node.js 使用事件驱动模型,当webserver接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。

当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。

这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。
(这也被称之为非阻塞式IO或者事件驱动IO)

在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。

深入浅析Node.js 事件循环

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件,如下实例:

//引入events模块
var events = require('events');
//创建eventEmitter对象
var eventEmitter = new events.EventEmitter();
//创建事件处理程序
var connectHandler = function connected() {
 console.log('连接成功。');
 //触发data_received事件 
 eventEmitter.emit('data_received');
}
//绑定connection事件处理程序
eventEmitter.on('connection', connectHandler);
//使用匿名函数绑定data_received事件
eventEmitter.on('data_received', function(){
 console.log('数据接收成功。');
});
//触发connection事件 
eventEmitter.emit('connection');
console.log("程序执行完毕。");

以上代码输出的结果是:

连接成功。

数据接收成功。

程序执行完毕。

上述的结果正如你想的一样,通过这种事件驱动模型我们就可以实现异步操作的。

(例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。)

var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
 if (err){
 console.log(err.stack);
 return;
 }
 console.log(data.toString());
});
console.log("程序执行完毕。");

以上代码输出的结果是:

程序执行完毕。

input.txt的内容。

从上述代码可以看出fs.readFile可以分发事件,当然Node.js里面的许多对象都会分发事件,一个net.Server对象会在每次有新连接时也会分发一个事件, 所有这些产生事件的对象都是 events.EventEmitter 的实例。

不过大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。

为什么要这样做呢?原因有两点:

首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发射应该是一个对象的方法。
其次 JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。

下面给大家分享我的第一个NodeJs项目

Node.js的安装通常有两种方式:自己编译源代码和使用编译好的文件,我这里使用编译好的文件
目前我的home目录下有刚下载来的node-v4.2.3-linux-x64

1.首先解压缩

tar xvf node-v4.2.3-linux-x64

2.设置链接,设置链接的目的在于任何路径都能够用到node命令

ln -s /home/node-v4.2.3-linux-x64/bin/node /usr/local/bin/node

ln -s /home/node-v4.2.3-linux-x64/bin/npm /usr/local/bin/npm

3.在home文件夹下建个目录叫mynodeproj,然后再建了个文件叫server.js(当然也可以起别的名字)

var http = require('http');
http.createServer(function (request, response) {
 //发送 HTTP 头部 
 //HTTP 状态值: 200 : OK
 //内容类型: text/plain
 response.writeHead(200, {'Content-Type': 'text/plain'});
 //发送响应数据 "Hello World"
 response.end('Hello World\n');
}).listen(8888);
//终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');

4.使用node命令执行以上代码

node server.js

执行上述命令之后会在命令行中显示"Server runnint at http://127.0.0.1:8888/",这样表示程序已经执行成功了!

因为我这个服务器是在阿里云里跑起来的,所以只要在外面的浏览器中键入阿里云IP+端口就可以访问了。

深入浅析Node.js 事件循环

Javascript 相关文章推荐
用javascript判断IE版本号简单实用且向后兼容
Sep 11 Javascript
javascript 终止函数执行操作
Feb 14 Javascript
JavaScript更改原始对象valueOf的方法
Mar 19 Javascript
JS实现Fisheye效果动感放大菜单代码
Oct 21 Javascript
纯javascript响应式树形菜单效果
Nov 10 Javascript
bootstrap 下拉多选框进行多选传值问题代码分析
Feb 14 Javascript
原生js实现选项卡功能
Mar 08 Javascript
详解vuex 中的 state 在组件中如何监听
May 23 Javascript
微信小程序实现移动端滑动分页效果(ajax)
Jun 13 Javascript
jQuery实现可编辑表格并生成json结果(实例代码)
Jul 19 jQuery
jQuery实现的简单歌词滚动功能示例
Jan 07 jQuery
如何使用webpack打包一个库library的方法步骤
Dec 18 Javascript
JavaScript控制浏览器全屏及各种浏览器全屏模式的方法、属性和事件
Dec 20 #Javascript
基于jQuery和CSS3制作响应式水平时间轴附源码下载
Dec 20 #Javascript
jQuery mobile 移动web(4)
Dec 20 #Javascript
基于jQuery实现放大镜特效
Oct 19 #Javascript
jQuery mobile 移动web(6)
Dec 20 #Javascript
jquery mobile 移动web(5)
Dec 20 #Javascript
js倒计时抢购实例
Dec 20 #Javascript
You might like
2019年漫画销量排行榜:鬼灭登顶 海贼单卷制霸 尾田盛赞鬼灭
2020/03/08 日漫
php中使用ExcelFileParser处理excel获得数据(可作批量导入到数据库使用)
2010/08/21 PHP
详解php魔术方法(Magic methods)的使用方法
2016/02/14 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
2017/08/31 PHP
PHP保留两位小数的几种方法
2019/07/24 PHP
laravel利用中间件做防非法登录和权限控制示例
2019/10/21 PHP
基于datagrid框架的查询
2013/04/08 Javascript
JavaScript运算符小结
2015/06/03 Javascript
JS实现超简单的仿QQ折叠菜单效果
2015/09/21 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
学习JavaScript设计模式之迭代器模式
2016/01/19 Javascript
移动开发之自适应手机屏幕宽度
2016/11/23 Javascript
jQuery插件echarts实现的单折线图效果示例【附demo源码下载】
2017/03/04 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
2017/08/10 Javascript
Js利用console计算代码运行时间的方法示例
2017/09/24 Javascript
详解使用React.memo()来优化函数组件的性能
2019/03/19 Javascript
layui checkbox默认选中,获取选中值,清空所有选中项的例子
2019/09/02 Javascript
微信h5静默和非静默授权获取用户openId的方法和步骤
2020/06/08 Javascript
Python修改Excel数据的实例代码
2013/11/01 Python
django上传图片并生成缩略图方法示例
2017/12/11 Python
在python中利用numpy求解多项式以及多项式拟合的方法
2019/07/03 Python
python发qq消息轰炸虐狗好友思路详解(完整代码)
2020/02/15 Python
css3 clip实现圆环进度条的示例代码
2018/02/07 HTML / CSS
魅力惠奢品线上平台:MEI.COM
2016/11/29 全球购物
俄罗斯香水和化妆品购物网站:Л’Этуаль
2018/05/10 全球购物
农救科工作职责
2013/11/27 职场文书
文言文形式的学生求职信
2013/12/03 职场文书
优秀医生事迹材料
2014/02/12 职场文书
《穷人》教学反思
2014/04/08 职场文书
软件项目开发计划书
2014/05/01 职场文书
申论倡议书范文
2014/05/13 职场文书
运动会稿件100字
2014/09/24 职场文书
2014三年级班主任工作总结
2014/12/05 职场文书
工作自我评价范文
2015/03/05 职场文书
MongoDB balancer的使用详解
2021/04/30 MongoDB
SQLServer RANK() 排名函数的使用
2022/03/23 SQL Server