Node.js API实例讲解——EventEmitter
EventEmitter
当继承EventEmitter,成为其子类就具备了emit激发事件方法和addListener添加监听器的方法。在node.js核心库中很多类都继承自EventEmitter,例如前面章节介绍的stream和socket等操作,有类似于 on("...",function(){}) 的写法。
下面做一个实例:
var EventEmitter = require("events").EventEmitter, inherits = require("util").inherits; // 定义一个EventEmitter子类 function User(name){ EventEmitter.call(this); this._name = name; } inherits(User,EventEmitter); User.prototype.changeName = function(name){ this._name = name; // 激发change name事件 this.emit("change name",name); } // 创建一个User对象 var me = new User("leo"); me.on("change name",function(newName){ console.log("名字被改成成 ---> " + newName); }); me.changeName("brighthas");
User类继承了EventEmitter,changeName被调用后,通过emit激发change name事件。后面创建一个User对象me,通过me.on方法添加一个change name事件的监听器,后面调用me.changeName方法后,激发了change name事件,从而调用了监听器,打印出:
名字被改成成 ---> brighthas
下面详细分析一下EventEmitter对象所具备的方法。
添加监听器
emitter.addListener(event, listener) 和 emitter.on(event, listener) 方法写法不同而已,都是向emitter对象添加监听器,event是事件名称,listener是监听器函数。
googogemitter.once(event, listener) 和 emitter.on 用法一致,区别是添加的监听器只监听一次,如果第二次发生同样事件,事件监听器将不会被执行。
emitter.on("event name",function(arg0,arg1 ...){ ... })
监听器参数取决于emit激发事件时的赋值,emitter.emit("event name",111,222,234),那么监听器的实参arguments的值是 [111,222,333]。
激发事件
通过emitter.emit方法激发事件。emitter.emit(event, [arg1], [arg2], [...])
删除事件监听器
通过emitter.removeListener(event, listener)方法,可以删除event事件的listener监听器,看如下代码。
var EventEmitter = require("events").EventEmitter, inherits = require("util").inherits; // 定义一个EventEmitter子类 function User(name){ EventEmitter.call(this); this._name = name; } inherits(User,EventEmitter); User.prototype.changeName = function(name){ this._name = name; // 激发change name事件 this.emit("change name",name); } // 创建一个User对象 var me = new User("leo"); // 第一个监听器 function handle1(name){ console.log("handle1 --- > 新名字:"+name); } // 第二个监听器 function handle2(name){ console.log("handle2 --- > 新名字:"+name); } me.on("change name",handle1); me.on("change name",handle2); me.changeName("brighthas");
这个代码结果是:
handle1 --- > 新名字:brighthas handle2 --- > 新名字:brighthas
如果把代码改一下,在 me.on("change name",handle2); 之后加上一行代码,在执行看看效果。
... me.on("change name",handle1); me.on("change name",handle2); // 新添加的代码 me.removeListener("change name",handle1); me.changeName("brighthas");
执行结果:
handle2 --- > 新名字:brighthas
通过me.removeListener("change name",handle1) 这行代码删除了change name 事件的handle1监听器,这样当激发change name 事件时,只有handle2监听器被执行。
emitter.removeAllListeners([event]) 如果这个方法的 event 参数没有指定那个事件,那么将会删除emitter对象内的全部事件监听器。如果指定了事件名称,那么会删除这个事件全部的监听器。
emitter.listeners(event)
这个方法是返回指定事件的全部监听器。
emitter.setMaxListeners(n)
这个是设置针对一个事件最多能添加多少监听器,默认是10。 如果超过这个值会有警告提示,程序还是会照常运行。
以上是对象方法,下面介绍一下类方法。
EventEmitter.listenerCount(emitter, event)
这个类方法可以得到emitter的event事件的监听器数量。
emitter本身发出的事件
newListener事件,当通过 emitter.on / emitter.once 添加监听器时会触发该事件。
removeListener 事件,当通过 emitter.removeAllListeners / emitter.removeListener 删除监听器时会触发该事件。
看下面代码:
var EventEmitter = require("events").EventEmitter, inherits = require("util").inherits; // 定义一个EventEmitter子类 function User(name){ EventEmitter.call(this); this._name = name; } inherits(User,EventEmitter); User.prototype.changeName = function(name){ this._name = name; // 激发change name事件 this.emit("change name",name); } // 创建一个User对象 var me = new User("leo"); // 第一个监听器 function handle1(name){ console.log("handle1 --- > 新名字:"+name); } // 第二个监听器 function handle2(name){ console.log("handle2 --- > 新名字:"+name); } // 添加 newListener事件监听 me.on("newListener",function(event,listener){ console.log(event + "事件添加了一个监听器") }) // 添加 removeListener事件监听器 me.on("removeListener",function(event,listener){ console.log(event+"事件删除了一个监听器"); }) me.on("change name",handle1); me.on("change name",handle2); // 删除全部事件监听器 me.removeAllListeners(); me.changeName("brighthas");
打印结果:
removeListener事件添加了一个监听器 change name事件添加了一个监听器 change name事件添加了一个监听器 newListener事件删除了一个监听器 change name事件删除了一个监听器 change name事件删除了一个监听器
【小结】
这里要说明的是,很多人会把并发 I/O非阻塞 等概念和事件概念有混淆,至少是部分混淆,其实毫无关系。事件也不能决定是异步还是同步,这个取决于底层。