Solution Implementation
We're tasked with creating an EventEmitter
class that can manage various event subscriptions and trigger these events when needed. Essentially, we're building the underpinnings of a custom event-handling system.
Why Use a Map for Subscriptions?
The subscriptions
Property
The first thing to note is the subscriptions
property, which is a JavaScript Map. A Map in JavaScript holds key-value pairs and remembers the original insertion order of the keys. This makes it an excellent choice for our subscription management because we can store the event names as keys and their respective callbacks as values.
Benefits of Using a Map
- Order Preservation: Unlike objects, the order of elements is preserved. This could be useful if the order of subscription or event triggering matters.
- Better Performance: Map operations like
get
,set
,has
, anddelete
are generally faster than their object counterparts.
The subscribe
Method: The Heart of the EventEmitter

Step 1: Initialize the Event Subscription
When someone wants to subscribe to an event, they'll use the subscribe
method, passing in the eventName
and a callback
function to execute when that event is emitted.
Here's the part of the code that ensures that an entry for this eventName
exists in the subscriptions
map:
1if (!this.subscriptions.has(eventName)) {
2 this.subscriptions.set(eventName, new Set());
3}
Why Use a Set for Callbacks?
We use a Set to store all callbacks associated with a particular eventName
. The Set ensures that each callback is unique, preventing duplicate callbacks for the same event.
Step 2: Add the Callback
Once we have ensured that an entry exists for the eventName
, the next step is to add the callback
to this event's subscriptions:
1const subscriptions = this.subscriptions.get(eventName);
2const callbackObj = { callback };
3subscriptions.add(callbackObj);
We wrap the callback
in an object (callbackObj
). This gives us more flexibility for future enhancements, like adding additional metadata to the subscription.
Step 3: Return a Release Function
The method returns a release
function that allows the subscriber to unsubscribe from the event:
1return {
2 release: () => {
3 subscriptions.delete(callbackObj);
4 if (subscriptions.size === 0) {
5 delete this.subscriptions.eventName;
6 }
7 },
8};
When the release
function is invoked, it removes the callbackObj
from the Set of subscriptions. If there are no more subscriptions for this event, it also removes the eventName
entry from the subscriptions
map.