事件机制是node中另一个重要的机制,所有使用到事件的模块都是基于这个机制。在熟悉其他核心模块之前,有必要先学习一下node中的基础模块。
- 1.on、emit、once方法
先来了解下实例中两个最基本的方法:on、emit,以下是文档中给出的示例
const EventEmitter = require('event') // 引入event模块
class MyEmitter extents EventEmitter {}
const myEmitter = new MyEmitter() // 生成新实例
myEmitter.on('event',() => { // 新实例通过on方法绑定事件
console.log(666)
})
myEmitter.once('check',() => { // once指事件只会被触发一次
console.log(777)
})
myEmitter.emit('event') //通过emit触发事件
还是有点懵逼?那么我们找一些核心模块中的事件来瞅一瞅~
示例取自http模块中的http.Server类~
const http = require('http') // 引入http模块
const server = http.createServer((req,res) => { // 创建一个服务,即server类
res.writeHead(200, {'Content-Type':'text/html'}) // 定义响应头部
res.end('Hello World') // 结束相应
})
server.on('clientError',(req,res) => { // 给实例绑定clientError事件
console.log(666)
})
当客户端触发了error事件便会执行clientError,emit在内部执行
所有能触发事件的对象都是 EventEmitter 类的实例,都具有on和emit方法
如果你使用的是vue框架的话,你会发现这和vue组件中的事件机制很相似,都是通过on与emit来控制事件的绑定与触发
- 2.监听器(即触发函数)传入参数与this
const EventEmitter = require('event')
const myEmitter = new EventEmitter()
myEmitter.on('checkIt',function(a,b,c){
console.log(a,b,c,this) // 一个普通的监听器函数中,this指向当前实例(这里指的是myEmitter)
【注】:如果监听器使用了箭头函数,那么this的指向就不会指向当前实例
})
myEmitter.emit('checkIt',a,b,c) // 以此种方式向监听器函数中传参数
- 3.监听器函数的异步 setImmediate() 、process.nextTick()
监听器所绑定的函数默认是同步执行的,要想监听器函数异步执行可以使用以上两种方法。
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('这个是异步发生的');
});
});
myEmitter.emit('event', 'a', 'b');
- 4.错误事件
在当前实例运行发生错误时,会主动触发error事件。如果未定义error事件那么node会抛出错误并且退出node进程。
【注】:为了防止进程崩溃,可以在 process 对象的 uncaughtException 事件上注册监听器。但不建议这种做法,所以尽量为error事件注册监听器函数
const myEmitter = new MyEmitter();
process.on('uncaughtException', (err) => {
console.error('有错误');
});
myEmitter.emit('error', new Error('whoops!'));
// 打印: 有错误
- 5.newListener事件
newListener事件监听当前实例是否绑定新的监听器,需要注意的是此事件的触发时间是在你调用on方法为当前实例绑定新的监听器,但内部还未执行之前。以下是示例:
const myEmitter = new myEmitter()
myEmitter.once('newListener',function(event,listener){ //绑定newListener事件
if(event == 'event'){
myEmitter.on('event',function(){ // 上面之所以用once是因为当绑定event时会触发这里再绑定event,会陷入循环
console.log(666)
})
}
})
myEmitter.on('event',function(){ // 这里,绑定的的时候已经触发了上面的newListener。触发newListener时,这里的事件还没有被绑定上去。
console.log(777)
})
myEmitter.emit('event')
// console.log(666)
// console.log(777)
-
6.removeListener事件
removeListener事件与newListener事件类似。当移除监听器时会被触发,与newListener事件不同的是:removeListener事件是在移除之后才会触发 - 7.事件实例上的其他属性
介绍完了事件机制的基础知识,我们可以大致的过一下实例本身还有哪些其他属性与方法
1、emitter. eventNames() //获取当前实例上都绑定了哪些事件
2、emitter. getMaxListeners() //获取当前实例,单个事件可以最多绑定多少监听器
3、emitter. listenerCount(eventname) //获取某个事件有多少监听器,eventname为事件名称
4、emitter. listeners(eventname) // 获取某个事件的监听器副本。
5、emitter. prependListener(event,listener) // 绑定事件,但不同于on,会将事件添加到监听器数组前面,触发了事件emitter.prependListener()绑定的事件先执行
6、emitter. prependOnceListener(event,listener) // 绑定事件,只绑定一次,也会将事件添加到监听器数组最前面
7、emitter. removeAllListeners([eventName]) // 移除所有监听器
【注】:一旦事件被触发,那么直到最后一个监听器被执行完之前,remove都是没有意义的
8、emitter. removeListener(eventName, listener) // 移除指定事件的监听器
【注】:移除监听器每次只会移除一个,同名的多个监听器需要多次去除
9、emitter.setMaxListeners(n) // 设置当前实例,每个事件最多绑定多少个监听器
【注】:Infinity(或 0)表明不限制监听器的数量