跳到主要内容

EventEmitter

2024年10月14日
柏拉文
越努力,越幸运

一、EventEmitter


1.1 认识

所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象开放了一个 eventEmitter.on() 函数,允许将一个或多个函数绑定到会被对象触发的命名事件上。 事件名称通常是驼峰式的字符串,但也可以使用任何有效的 JavaScript 属性名。

EventEmitter 对象触发一个事件时,所有绑定在该事件上的函数都被同步地调用。 监听器的返回值会被丢弃。

EventEmitter 类由 events 模块定义和开放的

1.2 语法

const EventEmitter = require("events");

1.3 场景

1.4 实现

class EventEmitter{
constructor(){
this.events = new Map();
}
on(event,handler){
const handlers = this.events.get(event);
const added = handlers && handlers.push(handler);
if(!added){
this.events.set(event,[handler]);
}
}
off(event,handler){
const handlers = this.events.get(event);
if(handlers){
handlers.splice(handlers.indexOf(handler) >>> 0,1);
}
}
emit(event,...args){
const handlers = this.events.get(event) || [];
handlers.map((handler)=>{
handler.call(this,...args);
});
}
once(event,handler){
const onceHandler = (...args)=>{
handler.call(this,...args);
this.off(event,onceHandler);
};
this.on(event,onceHandler);
}
listenerCount(event){
return this.events.has(event) ? this.events.get(event).length : 0;
}
}


const myEmitter = new EventEmitter();
myEmitter.on("event1", function (a, b) {
console.log("event1-1",a, b,this);
});
myEmitter.on("event1", function (a, b) {
console.log("event1-2",a, b,this);
});

myEmitter.emit("event1", "a 参数", "b 参数");
myEmitter.emit("event1", "a 参数", "b 参数");
console.log(myEmitter.listenerCount());

二、Event: 'newListener'


EventEmitter 实例会在一个监听器被添加到其内部监听器数组之前触发自身的 newListener 事件。注册了 newListener 事件的监听器会传入事件名与被添加的监听器的引用。事实上,在添加监听器之前触发事件有一个微妙但重要的副作用: 在newListener 回调函数中, 一个监听器的名字如果和已有监听器名称相同, 则在被插入到EventEmitter实例的内部监听器数组时, 该监听器会被添加到其它同名监听器的前面。

语法

const EventEmitter = require("events");
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

myEmitter.once("newListener",(event,listener)=>{
if(event === "event"){
console.log("event 事件开始注册")
}
});
myEmitter.on("event",function(a,b){
console.log(a,b)
})
myEmitter.emit("event","哈哈","嘻嘻");
  • eventName: <any> 要监听的事件的名称

  • listener: <Function> 事件的句柄函数

三、Event: 'removeListener'


removeListener 事件在 listener 被移除后触发。

语法

const EventEmitter = require("events");
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

myEmitter.once("newListener",(event,listener)=>{
if(event === "event"){
console.log("event 事件开始注册")
}
});
myEmitter.once("removeListener",(event,listener)=>{
if(event === "event"){
console.log("event 事件开始移除");
}
});

myEmitter.on("event",function(a,b){
console.log(a,b)
})
myEmitter.emit("event","哈哈","嘻嘻");
  • eventName: <any> 要监听的事件的名称

  • listener: <Function> 事件的句柄函数

四、emitter.addListener(eventName, listener)


语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.addListener("event",(a,b)=>{
console.log(a,b)
});

myEmitter.emit("event", "哈哈", "嘻嘻");

五、emitter.emit(eventName[, ...args])


按监听器的注册顺序,同步地调用每个注册到名为 eventName 事件的监听器,并传入提供的参数。如果事件有监听器,则返回 true ,否则返回 false

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.addListener("event",(a,b)=>{
console.log(a,b)
});

myEmitter.emit("event", "哈哈", "嘻嘻");

六、emitter.eventNames()


返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号。

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.on("event1",(a,b)=>{
console.log(a,b)
});
myEmitter.on("event2", (a, b) => {
console.log(a, b);
});

console.log(myEmitter.eventNames());

返回值

返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号。比如[ 'event1', 'event2' ]

七、emitter.getMaxListeners()


返回 EventEmitter 当前的最大监听器限制值,该值可以通过 emitter.setMaxListeners(n) 设置或默认为 EventEmitter.defaultMaxListeners

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

console.log(myEmitter.getMaxListeners());

返回值

返回 EventEmitter 当前的最大监听器限制值。比如10

八、emitter.listenerCount(eventName[, listener])


九、emitter.listeners(eventName)


返回名为 eventName 的事件的监听器数组的副本。

语法

server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// 打印: [ [Function] ]

十、emitter.off(eventName, listener)


十一、emitter.on(eventName, listener)


添加 listener 函数到名为 eventName 的事件的监听器数组的末尾。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventNamelistener 会导致 listener 被添加与调用多次。返回一个 EventEmitter 引用,可以链式调用。

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.on("event1", (a, b) => {
console.log(a,b);
}).on("event2",(a,b)=>{
console.log(a,b);
});
myEmitter.on("event3",(a,b)=>{
console.log(a,b);
});

myEmitter.emit("event1","a 参数","b 参数");

十二、emitter.once(eventName, listener)


添加一个单次 listener 函数到名为 eventName 的事件。 下次触发 eventName 事件时,监听器会被移除,然后调用。

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.once("event1", (a, b) => {
console.log(a,b);
})

myEmitter.emit("event1","a 参数","b 参数");
myEmitter.emit("event1", "a 参数1", "b 参数2");

十三、emitter.prependListener(eventName, listener)


添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventNamelistener 会导致 listener 被添加与调用多次。

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.prependListener("event1", (a, b) => {
console.log(a,b);
}).prependListener("event2",(a,b)=>{
console.log(a,b);
});
myEmitter.prependListener("event3",(a,b)=>{
console.log(a,b);
});

myEmitter.emit("event1","a 参数","b 参数");

十四、emitter.prependOnceListener(eventName, listener)


添加一个单次 listener 函数到名为 eventName 的事件的监听器数组的开头。 下次触发 eventName 事件时,监听器会被移除,然后调用。

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.prependOnceListener("event1", (a, b) => {
console.log(a,b);
})

myEmitter.emit("event1","a 参数","b 参数");
myEmitter.emit("event1", "a 参数1", "b 参数2");

十五、emitter.removeAllListeners([eventName])


移除全部或指定 eventName 的监听器。返回一个 EventEmitter 引用,可以链式调用。

十六、emitter.removeListener(eventName, listener)


从名为 eventName 的事件的监听器数组中移除指定的 listener

语法

const EventEmitter = require("events");
const myEmitter = new EventEmitter();

myEmitter.on("event1", (a, b) => {
console.log(a,b);
myEmitter.removeListener("event1",()=>{
console.log("开始移除事件");
});
})

myEmitter.emit("event1","a 参数","b 参数");

十七、emitter.setMaxListeners(n)


默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 此限制有助于寻找内存泄露。 但是,并不是所有的事件都要被限为 10 个。 emitter.setMaxListeners() 方法允许修改指定的 EventEmitter 实例的限制。 值设为 Infinity(或 0)表明不限制监听器的数量。

十八、emitter.rawListeners(eventName)


十九 emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])


参考资料


Node.js 中文网

从发布订阅模式入手读懂Node.js的EventEmitter源码