Nodejs是基于V8引擎实现的事件驱动IO。事件模块Events是Nodejs的核心模块之一,许多模块都继承自Event模块,因此也能够发射事件。例如,http模块创建HTTP服务器时,会发射"connect"事件,断链接时会发射“ close”事件。这些对象在Node中被称为:事件发射击器。需要处理这些事件的对象可以订阅事件,并将回调函数绑定到这些事件上。事件发射器发射事件时,对应的回调函数就会被调用。
理解事件机制
Nodejs事件的使用,会有一个事件发射器及一个或多个事件监听器。事件发射器指可以发射事件的对象,而事件监听器指绑定到事件上的处理代码。
一个简单的web服务器:
var http = require('http'); //创建一个HTTP服务顺 var server = http.createServer(); //监听request事件 server.on('request', function (req, res) { //对request事件的处理 res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World!') }); server.listen(3000)
在上面的示例中,创建了一个HTTP服务器。每当有web请求进入时,事件发射器(即:server对象)会发送一个'request'类型的事件,而通过'on'注册过的事件监听器里方法会被执行。事件发射器发射的事件是有类型的,如'request'就是一个事件类型,http对象除了有'request'事件外,还有:'connect'、'close'、'upgrade'等类型的事件。
事件发射器的使用
1.实现一个事件发射击器
Nodejs中,自定义一个事件发射非常简单,实现一个继承自event.EventEmitter的伪类。示例如下:
var util = require('util'); var em = require('events').EventEmitter; var MyClass = function() { // body... } util.inherits(MyClass, em);
inherits是util模块中方法用于复制父对象中的方法。如,上面的代码中util.inherits就是建立了一条原型链,使MyClass类具有了EventEmitter类的原型方法。
2.发射事件
继承EventEmitter类后,MyClass类的实例就可以发射事件了,添加一个事件发射器:
MyClass.prototype.sendEvent = function(){ this.emit("myEvent", 'arg 1', 'arg 2'); }
当MyClass类的实例调用sendEvent方法时,就会发送一个myEvent的事件。事件被发射的同时,还可以同时发送一些数据,上面示例中的:'arg 1'和'arg 2'就是被发送的数据。事件被发射时,两个字符串会做为参数发送给事件监听器。
下面实例化MyClass类,并在类实例中创建事件监听,及发送事件:
var myInstance = new MyClass(); //事件监听器 myInstance.on('myEvent', function(arg1, arg2){ console.log('这是监听到的事件,这个事件还发来了两个参数%s和%s', arg1, arg2); }) //事件发送器发射事件 myInstance.sendEvent(); //输出如下: 这是监听到的事件,这个事件还发来了两个参数arg 1和arg 2
事件发射器相关API
任何实现了EventEmitter类的对象,都具有了EventEmitter类中的方法。EventEmitter中的方法包括:
.addListener和.on:为指定类型的事件添加事件监听器 .once:为指定类型的事件添加一个仅使用一次的事件监听器 .removeListener:删除绑定到指定事件上的某个事件监听器 .removeAllListeners:删除绑定到指定事件上的所有事件监听器 .setMaxListeners:设置可添加的监听器的数量
1.使用.addListener()或.on()绑定回调函数
通过事件类型和回调函数,就可以注册事件发生时所要进行的操作,即添加事件监听。如上面示例中的myInstance.on()方法,就是添加了事件监听器。.on()方法是.addListener()的简写形式,二者在功能上完全一致。
事件发射器允许在同一类型的事件上绑定多个事件监听器,例如:
var myInstance = new MyClass(); //事件监听器 myInstance.on('myEvent', function(arg1, arg2){ console.log('这是监听到的事件,这个事件还发来了两个参数%s和%s', arg1, arg2); }) //另一个事件监听器 myInstance.on('myEvent', function(arg1){ console.log('这是另一个事件监听到器,这个事件只接受一个参数%s', arg1); }) //事件发送器发送事件 myInstance.sendEvent(); //以上代码输出如下: 这是监听到的事件,这个事件还发来了两个参数arg 1和arg 2 这是另一个事件监听到器,这个事件只接受一个参数arg 1
当添加多个事件监听器时,事件发射器会按照事件监听器的注册顺序依次调用监听事件。当其中一个事件发生错误时,其后注册的监听事件将不会再被调用。为防止因为监听器太多而可能导致内存泄漏,Nodejs默认允许对一类型事件添加10个监听器,超过10个将会得到一条警告。可以通以下方法设置可添加监听器的数量:
emitter.setMaxListeners(20); //设置为0时,则不限制监听器数量
2.使用.once()绑定仅执行一次的回调函数
如果想使监听器里面的函数只执行一次,可以使用.once()函数,.once()注册事件监听器后,会在第一个事件发生成删除事件监听。示例如下:
var myInstance = new MyClass(); //只执行一次的事件监听器 myInstance.once('myEvent', function(arg1, arg2){ console.log('这是一个只执行一次的事件监听器。这个监听器收到了两个参数%s和%s', arg1, arg2); }) //多次发送事件 myInstance.sendEvent(); myInstance.sendEvent(); //以上代码输出如下: 这是一个只执行一次的事件监听器。这个监听器收到了两个参数arg 1和arg 2
3.事件监听器的移除
如果需要删除绑定到指定事件上的某个事件监听器,可以调用removeListener()方法,通过事件类型和回调函数名来取消事件临听器的注册。示例如下:
var myInstance = new MyClass(); //监听函数1 function myListener1(arg1, arg2){ console.log('事件监听器1'); } //监听函数2 function myListener2(arg1, arg2){ console.log('事件监听器2'); } //添加事件监听器 myInstance.on('myEvent', myListener1); myInstance.on('myEvent', myListener2); //发送事件 myInstance.sendEvent(); //移除事件临器1 myInstance.removeListener('myEvent', myListener1); //再次发送事件 myInstance.sendEvent(); //以上代码输出如下: 事件监听器1 事件监听器2 事件监听器2
以上代码是移除了某事件类型的单个监听器,也可以调用.removeAllListeners()方法,移除某类型事件的所有的监听器。示例如下:
var myInstance = new MyClass(); //监听函数1 function myListener1(arg1, arg2){ console.log('事件监听器1'); } //监听函数2 function myListener2(arg1, arg2){ console.log('事件监听器2'); } //添加事件监听器 myInstance.on('myEvent', myListener1); myInstance.on('myEvent', myListener2); //发送事件 myInstance.sendEvent(); //按事件类型和监听函数名称移除监听器的注册 myInstance.removeAllListeners('myEvent'); //再次发送事件 myInstance.sendEvent(); //以上代码输出如下: 事件监听器1 事件监听器2