2694. Event Emitter
Implement a custom EventEmitter class to support subscribing to events and emitting them later.
📄 Problem Statement
- subscribe(eventName, callback): Adds a callback to the specified event. Returns an object with an
unsubscribe()method to remove the listener. - emit(eventName, args): Calls all subscribed callbacks for the event in the order they were added. Returns an array of their results.
⚠️ If no callbacks exist for the event, return an empty array. Each callback is guaranteed to be unique (no duplicates).
💡 Example
const emitter = new EventEmitter();
function onClick(arg) { return `Clicked ${arg}`; }
function onHover(arg) { return `Hovered ${arg}`; }
const sub1 = emitter.subscribe("click", onClick);
const sub2 = emitter.subscribe("click", onHover);
emitter.emit("click", [1]);
// ➞ ["Clicked 1", "Hovered 1"]
sub1.unsubscribe();
emitter.emit("click", [2]);
// ➞ ["Hovered 2"]
🧠 Explanation
We store a map of events to an array of listener objects. Each subscription is wrapped in a closure so it can be cleanly removed later using unsubscribe().
On emitting an event, we iterate through all relevant callbacks, passing in the arguments and collecting their return values.
✅ Your Solution
class EventEmitter {
constructor() {
this.events = {};
}
subscribe(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
const listener = { callback };
this.events[eventName].push(listener);
return {
unsubscribe: () => {
this.events[eventName] = this.events[eventName].filter(
l => l !== listener
);
}
};
}
emit(eventName, args = []) {
if (!this.events[eventName]) {
return [];
}
return this.events[eventName].map(listener => listener.callback(...args));
}
}