One Pager Cheat Sheet
- The document details the need for asynchronous functions and event-driven architecture in modern applications, where emitters emit named events triggering listener functions, while discussing the implementation of a class to emit events and subscribe to them using the
subscribe
andemit
methods respectively. - The article discusses how to create a custom event-handling system that allows users to subscribe and unsubscribe from events, and emit events, while considering the efficient management and notification of multiple subscribers for multiple events.
- The brute-force approach to tracking event subscriptions uses a JavaScript object where each key corresponds to an
eventName
and the value is an array of callback functions, but this method has issues with duplicate callbacks and inefficient unsubscription; to optimize, a Map data structure can be used for quick lookup and insertion, a Set can be used for callbacks to eliminate duplicates, and arelease
function can make unsubscription efficient. - The
EventEmitter
class, which serves as a custom event-handling system, uses a JavaScriptMap
for thesubscriptions
property to manage event subscriptions optimally, with order preservation and better performance, while the heart of this system, thesubscribe
method, initializes event subscriptions, adds thecallback
to the event's subscriptions, and returns arelease
function to allow unsubscribing, all while ensuring the uniqueness of eachcallback
with aSet
. - The
emit
method in theEventEmitter
class triggers an event and calls all the associated callbacks, with...args
syntax enabling the passage of any number of arguments to the callback functions.
This is our final solution.
To visualize the solution and step through the below code, click Visualize the Solution on the right-side menu or the VISUALIZE button in Interactive Mode.
xxxxxxxxxx
30
class EventEmitter {
subscriptions = new Map();
subscribe(eventName, callback) {
if (!this.subscriptions.has(eventName)) {
this.subscriptions.set(eventName, new Set());
}
const subscriptions = this.subscriptions.get(eventName);
const callbackObj = { callback };
subscriptions.add(callbackObj);
return {
release: () => {
subscriptions.delete(callbackObj);
if (subscriptions.size === 0) {
delete this.subscriptions.eventName;
}
},
};
}
emit(eventName, args) {
const subscriptions = this.subscriptions.get(eventName);
if (subscriptions) {
subscriptions.forEach((cbObj) => {
cbObj.callback.apply(this, args);
});
}
}
}
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment
That's all we've got! Let's move on to the next tutorial.
If you had any problems with this tutorial, check out the main forum thread here.