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