Node.js中使用事件发射器模式实现事件绑定详解_node.js(3)
readStream.on("data", function(data) {
console.log("got data from file read stream: %j", data);
});
前面说过,传递给回调函数的参数个数和签名依赖于具体的事件发射器对象和事件类型,它们并不是被标准化的,“data”事件可能传递的是一个数据缓冲对象,“error”事件传递一个错误对象,数据流的“end”事件不向事件监听器传递任何数据。
绑定多个事件监听器
事件发射器模式允许多个事件监听器监听同一个事件发射器的同一事件类型,比如:
I have some data here.
I have some data here too.
事件发射器负责按监听器的注册顺序调用指定事件类型上绑定的所有监听器,也就是说:
1.当事件发生后事件监听器可能不会被立刻调用,也许会有其它事件监听器在它之前被调用。
2.异常被抛出到堆栈是不正常的行为,可能是因为代码里有bug,当事件被发射时,如果有一个事件监听器在被调用时抛出了异常,可能会导致一些事件监听器永远不会被调用。这种情况下,事件发射器会捕获到异常,也许还会处理它。
看下面这个例子:
readStream.on("data", function(data) {
throw new Error("Something wrong has happened");
});
readStream.on("data", function(data) {
console.log('I have some data here too.');
});
因为第一个监听器抛出了异常,因此第二个监听器不会被调用。
用.removeListener()从事件发射器移除一个事件监听器
如果当你不再关心一个对象的某个事件时,你可以通过指定事件类型和回调函数来取消已注册的事件监听器,像这样:
function receiveData(data) {
console.log("got data from file read stream: %j", data);
}
readStream.on("data", receiveData);
// ...
readStream.removeListener("data", receiveData);
这个例子里,最后一行把一个可能在将来被随时调用的事件监听器从事件发射器对象移除了。
为了删除监听器,你必须给回调函数命名,因为在添加和删除的时候需要回调函数的名字。
使用.once()让回调函数最多执行一次
如果你想监听一个最多执行一次的事件,或者只对某个事件发生的第一次感兴趣,可以用.once()函数:
function receiveData(data) {
console.log("got data from file read stream: %j", data);
}
readStream.once("data", receiveData);
上面的代码,receiveData函数只会被调用一次。如果readStream对象发射了data事件,receiveData回调函数将会而且仅会被触发一次。
它其实只是个方便方法,因为很简单的就能实现它,像这样:
var EventEmitter = require("events").EventEmitter;
EventEmitter.prototype.once = function(type, callback) {
var that = this;
this.on(type, function listener() {
that.removeListener(type, listener);
callback.apply(that, arguments);
});
};
上面代码里,你重新定了EventEmitter.prototype.once函数,同时也重定义了每个继承自EventEmitter的所有对象的once函数。代码只是简单的使用.on()方法,一旦收到了事件,就用.removeEventListener()取消回调函数的注册,并调用原来的回调函数。