Coding Challenge Practice - Question 88
Source: Dev.to
Overview
Implement an EventEmitter that allows subscribing to events, emitting events with arguments, and releasing specific subscriptions.
Boilerplate
class EventEmitter {
subscribe(eventName, callback) {}
emit(eventName, ...args) {}
}
Each event name maps to an array of listener functions:
this.events = {};
Subscribe Method
- If the event does not exist, create an empty array for it.
- Append the callback to the array (duplicates are allowed).
- Return a subscription object with a
releasemethod that removes only this callback.
subscribe(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
let released = false;
return {
release: () => {
if (released) return;
released = true;
const listeners = this.events[eventName];
if (!listeners) return;
const index = listeners.indexOf(callback);
if (index !== -1) {
listeners.splice(index, 1);
}
}
};
}
Emit Method
- Retrieve the listeners for the given event.
- If none exist, exit.
- Call each listener with the provided arguments.
emit(eventName, ...args) {
const listeners = this.events[eventName];
if (!listeners) return;
listeners.forEach(callback => {
callback(...args);
});
}
Complete Implementation
class EventEmitter {
constructor() {
this.events = {};
}
subscribe(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
let released = false;
return {
release: () => {
if (released) return;
released = true;
const listeners = this.events[eventName];
if (!listeners) return;
const index = listeners.indexOf(callback);
if (index !== -1) {
listeners.splice(index, 1);
}
}
};
}
emit(eventName, ...args) {
const listeners = this.events[eventName];
if (!listeners) return;
listeners.forEach(callback => {
callback(...args);
});
}
}