什么是 EventEmitter?
EventEmitter
类是 Node.js 的内置类,位于 events
模块。根据文档中的描述:
大部分的 Node.js 核心 API 都是基于惯用的异步事件驱动的体系结构所实现的,在该体系结构中,某些类型的对象(称为“发射器”)发出已命名事件,这些事件会导致调用
Function
对象(“监听器”)”
EventEmitter
可以描述为发布-订阅的实现,通过 EventEmitter
可以实现事件的订阅和发布。
实现一个发布订阅功能,在大厂面试中出现的频率也是相对较高,那么本文将一步一步实现如何实现一个发布订阅功能。
EventEmitter 方法
方法 | 功能 |
---|---|
addListener(event, listener) | 新增一个新事件到数组 |
once(event, listener) | 绑定事件,只触发一次后移除 |
removeListener(event, listener) | 移除监听 |
setMaxListeners(n) | 设置最大监听数 |
listeners(event) | 返回监听数组 |
emit(event, [arg1], [arg2], [...]) | 触发事件 |
我们先创建一个基础类
class EventEmitter {
constructor() {
this._events = Object.create(null);
this._maxListeners = 10;
}
}
addListener
addListener(event, listener) {
(this._events[event] || (this._events[event] = []))[method](listener);
return this;
}
once
监听一次 once
比较特殊,我们可以在执行监听器回调的时候,移除监听器。这里创建一个 helper
函数。
once(event, listener) {
const self = this;
function helper() {
self.removeListener(event, helper);
listener.apply(this, arguments);
}
helper.listener = listener;
this.addListener(event, helper);
return this;
}
removeListener
removeListener(event, listener) {
const listeners = this._events[event];
if (!listeners) return this;
const index = listeners.indexOf(listener);
if (index !== -1) listeners.splice(index, 1);
return this;
}
setMaxListeners
setMaxListeners(n) {
this._maxListeners = n;
return this;
}
listeners
listeners(event) {
return this._events[event] || [];
}
emit
emit(event, [arg1], [arg2], [...]) {
const listeners = this._events[event];
if (!listeners) return this;
listeners.forEach(listener => {
listener.apply(this, arguments);
});
return this;
}
最终代码
class EventEmitter {
constructor() {
this._events = Object.create(null);
this._maxListeners = 10;
}
addListener(event, listener) {
(this._events[event] || (this._events[event] = []))[method](listener);
return this;
}
once(event, listener) {
const self = this;
function helper() {
self.removeListener(event, helper);
listener.apply(this, arguments);
}
helper.listener = listener;
this.addListener(event, helper);
return this;
}
removeListener(event, listener) {
const listeners = this._events[event];
if (!listeners) return this;
const index = listeners.indexOf(listener);
if (index !== -1) listeners.splice(index, 1);
return this;
}
setMaxListeners(n) {
this._maxListeners = n;
return this;
}
listeners(event) {
return this._events[event] || [];
}
emit(event, [arg1], [arg2], [...]) {
const listeners = this._events[event];
if (!listeners) return this;
listeners.forEach(listener => {
listener.apply(this, arguments);
});
return this;
}
}