在node中有一个核心的概念就是事件,很多的node模块都是基于事件的。事件就是提示程序中发生了什么的信号。
例如node中的http模块,它是可以用来创建网络服务的。我们监听给定的端口,每次我们在这个端口得到请求,http类就会发起一个事件,我们的工作就是响应这个事件,具体说就是读取请求内容并给出对应的反馈。在node的官方文档中也可以看到不同的模块发起不同的事件,我们的代码就是关心如何反馈这些事件。
回到node官方文档,在列表中看到有Event模块,模块里有个类叫做EventEmitter。这是node的核心模块之一,很多类是基于这个EventEmitter类的。
emitter设置为一个EventEmitter对象,在实际应用中会使用到。
emit就遍历了所有的监听器。这就是发起事件和处理用EventEmitter类来处理事件的基本内容。
经常我们在发起时间的时候想带点数据,例如在另一个logger模块中当我们记录日志时,我们的服务可能想创建一个日志的编号之后再返回给客户端。或者给它一个url,可以直接访问日志的信息。所以在上面的发起事件中,可以带一个参数作为事件的参数。
在现实编程中很少直接使用EventEmitter,相反都会创建一个类拥有所有EventEmitter的功能然后使用它。
现在创建一个文件logger,写入以下的代码。在这个模块中我们导出了logger函数。
app模块中我想监听然后做点事。导入EventEmitter到模块中,创建实例对象在应用中使用。在logger模块中发起事件。
app模块中注册监听器,接受返回的信息。
EventEmitter,自然创建的实例对象也只是作用与当前文件或是模块内。那么怎么办呢?
这里就要创建一个继承并扩展EventEmitter所有能力的类。这里我们创建一个Logger的类,并且拥有一个扩展的log方法。使用到ES6中的class。
分别改造下logger.js和app.js文件的代码
//引入模块
const EventEmitter = require('events');
let url = 'http://mylogger.io/log';
class Logger extends EventEmitter {
log(message) {
//发送http请求
console.log(message);
//emit是用来发起一个事件的
this.emit('messageLogged', {
id: 1,
url
});
}
}
module.exports = Logger;
//引入模块
const Logger = require('./logger');
const logger = new Logger();
//注册一个监听器,接收返回的信息
logger.on('messageLogged', (result) => {
console.log('监听成功');
console.log(result);
})
logger.log('hello node');
重新在控制台执行下,成功了
如果你想在程序中使用监听器来监测某个事件的发生,你需要创建一个扩展自EventEmitter的类,这样这个类就具有了EventEmitter所有的功能,同时你也可以添加任何自定义的功能。而在类中,如果你想发起事件,就使用emit方法。上面的this关联到自己,也就是从EventEmitter扩展出来的类,所以只要在EventEmitter中定义的成员也会包含于新的类中。
最后在app模块中,之前使用EventEmitter的对象,现在可以使用新的类定义一个实例对象。这个类扩展自EventEmitter类。