node学习之Events和EventEmitter

xiaoxiao2021-02-28  128

node学习之Events和EventEmitter对象

在node中,对于可以产生事件并能通过on方法绑定事件处理函数的对象来说,几乎都是通过继承EventEmitter来实现的,在本文中就是本人学习EventEmitter的一些理解。

1. 什么是EventEmitter?

EventEmitter是node提供的可以为其他对象提供异步事件处理功能的对象。

2. 创建EventEmitter对象实例:

var events = require('events') var EventEmitter = new events.EventEmitter()

3. 激发对象事件的方法: emit()

示例1:设置每隔1秒,就将计数信息定时输出到控制台,直到程序被终止

//每隔1秒,就将计数信息定时输出到控制台,直到程序被终止 var events = require('events') var em = new events.EventEmitter() var count = 0 setInterval(function () { em.emit('time', count++) },1000) em.on('time', function (data) { console.log('time '+ data) })

示例2: 通过继承EventEmitter创建支持事件功能的对象

//通过继承EventEmitter创建支持事件功能的对象 var util = require('util') var eventEmitter = require('events').EventEmitter var fs = require('fs') //创建一个新对象:inputChecker function inputChecker(name, file) { this.name = name; //使用node文件系统模块来创建一个可写流 this.writeStream = fs.createWriteStream('./' + file + '.txt',{'flags':'a','encoding':'utf-8','mode':0666}) } /** 在对象上使用util.inherits方法后,就可以在定义该对象的方法时调用emit方法来激发事件, * 同时也可以为该对象的实例编写事件处理函数. */ util.inherits(inputChecker, eventEmitter) //创建对象的一个方法:check,用于输入数据中解析特定命令信息 inputChecker.prototype.check = function check(input) { var command = input.toString().trim().substr(0,3) if(command == 'wr:'){ //触发write事件 this.emit('write',input.substr(3, input.length)) }else if(command == 'en'){ // 触发end事件 this.emit('end', input) }else{ //无法解析命令时,触发echo事件 this.emit('echo', input) } } var ic = new inputChecker('Cynthia', 'output') //将信息写入到可写流writeStream中 ic.on('write', function (data) { this.writeStream.write(data, 'utf-8') }) //将收到的信息回车显示到控制台中 ic.on('echo', function (data) { console.log(this.name + ' wrote ' + data) }) /* //echo事件的另一种写法法 ic.addListener('echo', function (data) { console.log(this.name + ' wrote ' + data) }) */ // 使用process.exit方法结束并退出程序 ic.on('end', function () { process.exit() }) process.stdin.resume() //开启标准输入流 process.stdin.setEncoding('utf-8') //设置编码 process.stdin.on('data',function (input) { ic.check(input) })

说明:

在示例2中,并没有在构造函数中调用EventEmitter构造函数,是因为需要的on和emit方法定义在EventEmitter的原型中,并没有定义在实例属性中,on方法就像是EventEmitter.listener方法的别名,所以示例中可以看到echo事件还有其他写法。

4. 关于事件处理函数的数量限制问题

在默认情况下,一个事件最多挂载10个处理函数,如果过于10个处理函数,那么多出的处理函数也会执行,但是会抛出警告信息。

解决的办法: 用setMaxListener(number)方法传入一个数字number表示最多能挂载的处理函数个数。

注意,如果处理函数超过这个数,程序仍然会正常执行但是也会警告提示,并且当number等于0时候,表示无限制。

示例3: 解决事件处理函数的个数限制问题

//解决事件处理函数的个数限制问题 var events = require('events') var student = new events.EventEmitter() //设置监听事件的最大数目 student.setMaxListeners(11) //添加事件处理函数 student.on('student',function (number) { console.log('My student ID is ' + number + ' 1') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 2') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 3') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 4') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 5') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 6') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 7') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 8') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 9') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 10') }) student.on('student',function (number) { console.log('My student ID is ' + number + ' 11') }) //执行事件 student.emit('student','No.')

结果:

如果在上面代码中,再多添加一段:

student.on('student',function (number) { console.log('My student ID is ' + number + ' 12') })

那么结果如下:

可以看到,会有警告信息出现。

6. 事件处理函数的执行顺序

我们了解到,一个事件绑定可以多个事件处理函数,那么,事件发射器就会负责按照事件绑定的事件处理函数的注册顺序依次调用事件处理函数,也就是说,如果某个事件处理函数也许并不会在事件发生之后立即被调用,也许在它之前还会有别的事情。

示例4:

//在这个例子中,第二个事件处理函数不会被调用,因为第一个事件处理函数抛出了一个错误 var events = require('events') var eventEmitter = new events.EventEmitter() eventEmitter.on('data', function (data) { throw new Error('Something wrong has happened !') }) eventEmitter.on('data', function (data) { console.log('I have some data here , too !') })

7. EventEmitter对象的其他方法

EventEmitter对象除了上述用中用到的.on() , .addListerner()方法,还有一些其他的方法。

.once() , 为指定类型的事件绑定一个仅仅只会被调用一次的事件监听器。 .removeEventListener() , 删除指定事件上的某个事件监听器,即事件处理函数。 .removeAllEventListener() , 删除所有事件的或者指定事件上的所有事件监听器。

例5:判断事件处理函数是否执行

在例3的最后一行代码,即emit()方法,替换成以下的代码: //判断事件处理函数是否执行 student.on('teacher',function (number) { console.log('My duty is ' + number + ' 1') }) student.on('teacher',function (number) { console.log('My duty is ' + number + ' 2') }) //判断事件是否被执行 var hasConfortListener = student.emit('student','No.') var hasLovedListener = student.emit('teacher','techer.') var hasPlayedListener = student.emit('monitor','Only') console.log(hasConfortListener) // true (表示事件处理函数已被执行) console.log(hasLovedListener) // true console.log(hasPlayedListener) // false (表示没有执行该事件处理函数)

结果:

例6: 计算事件被监听的个数

继续在例5的代码后面添加代码: //计算事件被监听的个数 var result1 = student.listeners('student').length console.log(result1) // 9 var result2 = events.EventEmitter.listenerCount(student, 'student') console.log(result2) // 9

结果:

例7: 删除事件处理函数

var events = require('events') var student = new events.EventEmitter() student.setMaxListeners(11) //设置监听事件的最大数目 function fun1(number) { console.log('My student ID is ' + number + ' 1') } student.on('student', fun1) function fun2(number) { console.log('My student ID is ' + number + ' 1') } student.on('student', fun2) student.on('student', function (number) { console.log('My student ID is ' + number + ' 3') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 4') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 5') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 6') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 7') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 8') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 9') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 10') }) student.on('student', function (number) { console.log('My student ID is ' + number + ' 11') }) //执行事件 student.emit('student','No.') //删除事件(单个) student.removeListener('student',fun1) console.log(student.listeners('student').length) // 结果: 10 (原来有11个, 说明已经删除了1个) student.removeListener('student',fun2) console.log(student.listeners('student').length) // 结果:9 (在上面10个的基础上, 又删除了1个) //删除特定的事件(批处理) student.removeAllListeners('teacher') console.log(student.listeners('teacher').length) // 结果: 0 (原来设置有2个, 说明都被删除了) //删除所有的事件 student.removeAllListeners() console.log(student.listeners('student').length) // 结果:0

结果:

转载请注明原文地址: https://www.6miu.com/read-39868.html

最新回复(0)