node.js的事件机制


Posted in Javascript onFebruary 08, 2017

首先, 补充下对node 的理解:

nodeJs 是一个单进程单线程应用程序, 但是通过事件和回调支持并发, 所以性能非常高~

那么什么是单进程单线程呢~(写给语文跟我一样不好的小伙伴)

我们来看下单进程和多进程的区别:

1.  多进程的优势在于任务的独立性,比如某个任务单独作为一个进程的话,崩溃只影响自己的服务,其他任务不受影响.如果是多个任务在同一个进程内部利用多个线程进行处理,某个线程发生了未处理的异常的话,会导致整个进程完蛋,所有的任务跟着遭殃

2.  从资源分配上来说,多进程方案比多线程方案更加灵活和自由

3. 不过任务间的通信方面多进程要比多线程复杂些,编一个好的多进程通信方案要比多线程间的通信方案困难多了(小伙伴们注意区分进程和线程哟~)

以web server为例的话,比如我的服务器上架设了三个网站,如果是用一个进程管理的话, 网站A遭受攻击死掉了,意味着另外两个网站会出现同样的现象. 如果是分开独立的进程的话,三个网站互不影响

具体来分呢, 单进程对比多进程有什么优点呢:

1)  初期实现起来比较简单快速, 而且不用考虑进程间通信的工作量

2) 单一性使得部署和运营比较简单(这还用说  / 白眼ing)

3) 内存占用少, 不过呢, 现在内存很廉价, 但是一分钱也是钱呀!

4) 进程内部通信效率比IPC/scoket(多进程数据通讯的终端)等要高效,  我一嗓子你就听见了, 就不用费力气装个电话了

当然, 肯定优缺点!不然花那么多钱开多进程的人也太蠢了 ~

单进程对比多进程的缺点~

1) 中后期随着业务逻辑的复杂化和需求的增加,这个单进程会变得臃肿, 难以维护。 一个任务分解成多个进程会使单个进程的逻辑简单,而不容易出错

2) 同进程内模块间是强依赖关系,需要在一起编译相互的影响也比较大。 这相对于多进程间通信来说, 耦合度较大(不符合高内聚低耦合的伟大思想), 不利于多团队并行开发。 多进程更便于多语言的协作开发。

3)任何模块的崩溃都将导致整个进程的失效,多进程模式更加稳定健壮,业务处理程序隔离运行, 一个go home不会影响其他(你敢崩我也崩);

4) 性能问题: 如果不支持进程间数据通讯的话,单进程的容量是受限的, 这个性能瓶颈对于支持群组类服务的尤其需要考虑。多进程部署极其灵活,可以扩充机器数量来提高系统处理性能,还可以从硬件上避免单点故障。(一个人承受不来)

5) 单进程中多线程难调试( 一枪开出去, 一群人倒了, 我还得检查一下谁中枪了才能给你debug)

举个小栗子

你有一个对象, 对象特别挑食, 但是对象只喜欢一种菜, 你每天做给她吃。

这就是个单进程单线程的模型,  如果你做的不好吃了, 对象不吃了。

但是我有一个对象, 她喜欢吃10种菜, 我每天端过去10份, 哪天其中某一份醋放多了, 对象说真难吃, 今天不吃了。这就是单进程多线程的模型。一个菜不好吃导致对象不吃了(全部线程崩掉)

..  如果我有两个对象..  每个对象喜欢吃一种菜

ok,  一个对象觉得好吃, 吃的脸圆圆的三下巴, 一个觉得不好吃常年不吃, 骨瘦如柴。

这就是多进程单线程互不影响的模型.. 多进程多线程我就不举栗了 ~

说到这里, 小伙伴有没有对单进程单线程有一些理解呢。nodeJs 就是单进程单线程的应用程序, 进程间互不影响, 绑定多个事件可以同时触发~  不用等你完了我再有动作, 所以nodeJs性能很高。

nodeJs 单线程类似进入一个while(true ) 的事件循环, 知道没有事件观察者的时候退出(每绑定一个事件, 就生成一个事件观察者), 当有事件发生的时候, 就会调用该事件的回调函数。

事件驱动程序

nodeJs 使用事件驱动模型(稍后说), 当web server 接收到请求时, 就把它关闭然后进行处理, 然后去服务下一个web 请求。可以理解成我触发事件, 就先关闭这个事件驱动, 然后处理, 我觉得是在防止二次触发~ 造成不正确的负载和意料之外的结果,这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。(这也被称之为非阻塞式IO或者事件驱动IO)

可能有的小伙伴会问了, 什么是 事件驱动模型呢~ 

其实在了解事件驱动之前, 我们可以先看一下事件驱动的三大要素:

1) 事件源:  谁来接受外部事件

2) 侦听器:  能够接收事件源通知的对象

3) 事件处理程序:  用于处理事件

好, 包含以上三点的就是一个完整的事件驱动程序。

举个栗子

如果有一天你走在路上一不小心被天上掉下来的花瓶砸到了,并且晕死了过去。那么整个过程其实就是一个事件处理流程,而且我们可以非常方便的分析出刚才所提到的事件驱动模型中的三大要素。

1.被砸晕的这个人其实就是事件源,因为他是能够接受到外部的事件的源体。

2.侦听器就是这个人的大脑神经,因为它会感知到疼痛。

3.事件处理就是这个人晕死了过去。

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

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

说了那么多, 事件绑定怎么写呢。

在node 里, 有个事件模块 events,  我们可以通过实例化的events 对象 来绑定事件。

上代码:

var event = require('events'); // 引入事件模块
var eventObj = new event(); // 实例化一个事件对象
eventObj.on('起床', function() { // 绑定事件和事件回调
console.log('洗脸刷牙');

});
eventObj.emit('起床'); // 触发事件的方法

结果是符合预期的。

但是有一点需要注意哦, 当你想移除事件的时候, 直接eventObj.removeListener(‘起床')

然后各种报错~

其实正确的移除事件的方法是这样的~

上代码:

var event = require('events'); // 引入事件模块
var eventObj = new event(); // 实例化一个事件对象
function getUp() {
console.log('洗脸刷牙');
}
eventObj.on('起床', getUp);
eventObj.emit('起床');
eventObj.removeListener('起床', getUp);
eventObj.emit('起床');

成功移除事件~

node 还提供了只触发单次事件的方法~

eventObj.once(‘起床', getUp)

还有移除全部事件呀~

eventObj.removeAllListeners(getUp), 像我这样指定了getUp的事件, 则移除所有触发该事件的监听器。

eventObj.setMaxListeners(n)  参数是一个数字, 因为node默认了绑定事件最多10个, 10个以上的时候会警告。 如果不想被警告就设置最大监听器个数咯~

eventObj.listeners(even)  返回指定事件的监听器数组

eventObj.emit(getUp, [arg1], [arg2], [...])

按照参数的顺序执行事件,  返回值是true或者false。有此监听事件就返回true。

不知道小伙伴们有没有疑惑,  我明明已经把events 模块加载过来了, 为什么还要实例化才能用呢~ 

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

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

首先,具有某个实体功能的对象实现事件符合语义(可以自己命名了啊喂(#`O′) ), 事件的监听和发射都应该是一个对象的方法。

其次 JavaScript 的对象机制是基于原型的, 支持部分多重继承,继承 EventEmitter不会打乱对象原有的继承关系。

Node 应用程序是如何工作的?

在 Node 应用程序中,执行异步操作的函数将回调函数作为最后一个参数, 回调函数接收错误对象作为第一个参数。

接下来让我们来重新看下前面的实例,创建一个 input.txt ,文件内容如下:

123456123123

创建 main.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("程序执行完毕");

以上程序中 fs.readFile() 是异步函数用于读取文件。 如果在读取文件过程中发生错误,错误 err 对象就会输出错误信息。

如果没发生错误,readFile 跳过 err 对象的输出,文件内容就通过回调函数输出。

执行以上代码,执行结果如下:

123456123123

接下来我们删除 input.txt 文件,执行结果如下所示:

程序执行完毕Error: ENOENT, open 'input.txt'

因为文件 input.txt 不存在,所以输出了错误信息。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
jquery复选框checkbox实现删除前判断
Apr 20 Javascript
jquery实现鼠标拖拽滑动效果来选择数字的方法
May 04 Javascript
Javascript中浏览器窗口的基本操作总结
Aug 18 Javascript
原生js图片轮播效果实现代码
Oct 19 Javascript
bootstrap vue.js实现tab效果
Feb 07 Javascript
Vuejs仿网易云音乐实现听歌及搜索功能
Mar 30 Javascript
详解微信小程序设置底部导航栏目方法
Jun 29 Javascript
JS+HTML5实现图片在线预览功能
Jul 22 Javascript
微信小程序使用input组件实现密码框功能【附源码下载】
Dec 11 Javascript
layer.open弹层查看缩略图的原图,自适应大小的实例
Sep 05 Javascript
基于JS实现计算24点算法代码实例解析
Jul 23 Javascript
Vue看了就会的8个小技巧
Jan 21 Vue.js
jQuery多选框选择数量限制方法
Feb 08 #Javascript
Node.js连接MongoDB数据库产生的问题
Feb 08 #Javascript
简单实现bootstrap选项卡效果
Feb 08 #Javascript
Bootstrap导航条学习使用(一)
Feb 08 #Javascript
Vue过滤器的用法和自定义过滤器使用
Feb 08 #Javascript
Javascript中的神器——Promise
Feb 08 #Javascript
jquery获取下拉框中的循环值
Feb 08 #Javascript
You might like
php函数的常用方法及注意之处小结
2011/07/10 PHP
PHP屏蔽过滤指定关键字的方法
2014/11/03 PHP
在Windows系统下使用PHP生成Word文档的教程
2015/07/03 PHP
优化WordPress中文章与评论的时间显示
2016/01/12 PHP
PHP中set_include_path()函数相关用法分析
2016/07/18 PHP
PHP实现bitmap位图排序与求交集的方法
2016/07/28 PHP
PHP变量的作用范围实例讲解
2020/12/22 PHP
克隆javascript对象的三个方法小结
2011/01/12 Javascript
密码框显示提示文字jquery示例
2013/08/29 Javascript
jquery数组封装使用方法分享(jquery数组遍历)
2014/03/25 Javascript
jQuery监控文本框事件并作相应处理的方法
2015/04/16 Javascript
JS事件添加和移出的兼容写法示例
2016/06/20 Javascript
ajax图片上传,图片异步上传,更新实例
2016/12/30 Javascript
js中删除数组中的某一元素实例(无下标时)
2017/02/28 Javascript
javascript中json对象json数组json字符串互转及取值方法
2017/04/19 Javascript
Vue瀑布流插件的使用示例
2018/09/19 Javascript
解决vue加scoped后就无法修改vant的UI组件的样式问题
2020/09/07 Javascript
python list转dict示例分享
2014/01/28 Python
python样条插值的实现代码
2018/12/17 Python
python跳出双层for循环的解决方法
2019/06/24 Python
python调用自定义函数的实例操作
2019/06/26 Python
django 单表操作实例详解
2019/07/30 Python
Python使用python-docx读写word文档
2019/08/26 Python
Django数据库操作之save与update的使用
2020/04/01 Python
python 读取二进制 显示图片案例
2020/04/24 Python
keras分类模型中的输入数据与标签的维度实例
2020/07/03 Python
韩国三大免税店之一:THE GRAND 中文免税店
2016/07/21 全球购物
如何反序的迭代一个序列?how do I iterate over a sequence in reverse order
2012/02/04 面试题
质检的岗位职责
2013/11/17 职场文书
大学生家政服务项目创业计划书
2014/01/30 职场文书
离婚协议书包括哪些内容
2014/10/16 职场文书
2015元旦标语横幅
2014/12/09 职场文书
骨干教师个人总结
2015/02/11 职场文书
2015年乡镇流动人口工作总结
2015/05/12 职场文书
初中同学会致辞
2015/08/01 职场文书
爱心捐款倡议书:点燃希望,传递温暖
2019/11/04 职场文书