推荐答案
// www.javascriptcn.com code example
class EventEmitter {
constructor() {
this.events = {};
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
emit(eventName, ...args) {
if (this.events[eventName]) {
this.events[eventName].forEach(callback => {
callback(...args);
});
}
}
off(eventName, callback) {
if (!this.events[eventName]) {
return;
}
if(!callback){
delete this.events[eventName];
return
}
this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);
}
}
// 使用示例
const emitter = new EventEmitter();
const logMessage = (message) => {
console.log('Message:', message);
};
const logWarning = (message) => {
console.warn("Warning:", message)
}
emitter.on('message', logMessage);
emitter.on('message', logWarning);
emitter.emit('message', 'Hello, world!'); // 输出: Message: Hello, world! Warning: Hello, world!
emitter.off('message',logMessage)
emitter.emit('message', 'After Remove logMessage'); // 输出: Warning: After Remove logMessage
emitter.off('message')
emitter.emit('message','After Remove All message event') // 不输出任何内容本题详细解读
发布-订阅模式的概念
发布-订阅模式(Publish-Subscribe Pattern)是一种消息传递模式,它允许组件(发布者)发布消息,而无需知道哪些组件(订阅者)会接收这些消息。订阅者订阅感兴趣的消息类型,当发布者发布相应类型的消息时,订阅者会收到通知。这种模式实现了组件之间的松耦合,使得系统更易于扩展和维护。
实现思路
- 事件存储: 使用一个对象
this.events来存储事件及其对应的回调函数列表。键为事件名称(eventName),值为回调函数数组。 on方法(订阅):- 接收两个参数:事件名称
eventName和回调函数callback。 - 如果
this.events中不存在eventName的键,则创建一个新的空数组。 - 将
callback添加到this.events[eventName]数组中。
- 接收两个参数:事件名称
emit方法(发布):- 接收一个参数:事件名称
eventName和可变数量的参数...args,这些参数会传递给回调函数。 - 检查
this.events中是否存在eventName的键。 - 如果存在,则遍历
this.events[eventName]数组中的所有回调函数,并使用...args调用每一个回调函数。
- 接收一个参数:事件名称
off方法(取消订阅):- 接收两个参数:事件名称
eventName和可选的回调函数callback。 - 检查
this.events中是否存在eventName的键,如果不存在则直接返回。 - 如果未传入
callback, 则删除this.events[eventName]所有订阅的事件。 - 如果传入了
callback,则过滤this.events[eventName]中的回调函数,将不等于callback的函数保留下来,以此移除指定的订阅。
- 接收两个参数:事件名称
代码详解
class EventEmitter: 定义一个EventEmitter类来封装发布-订阅逻辑。constructor(): 初始化this.events为空对象。on(eventName, callback): 实现了订阅功能,将回调函数添加到指定事件的回调数组中。emit(eventName, ...args): 实现了发布功能,遍历并执行指定事件的所有回调函数。off(eventName, callback): 实现了取消订阅功能,移除指定事件或指定事件下的指定回调函数。
示例代码解释
示例代码创建了一个 EventEmitter 实例,并使用 on 方法订阅了 message 事件的两个回调函数 logMessage 和 logWarning。 当使用 emit('message', 'Hello, world!') 发布消息时,两个回调函数都会被调用。之后调用 off 移除 logMessage , 再次调用 emit 只会执行 logWarning, 最后调用off('message') 移除所有 message 事件的订阅,后续调用 emit 不会执行任何订阅事件。