Events play a crucial role in JavaScript, allowing developers to create interactive and responsive applications. One powerful pattern for managing events is the Publisher-Subscriber (Pub/Sub) pattern. In this blog post, we'll explore how to create an Event Emitter in JavaScript using the Pub/Sub pattern, providing a robust foundation for managing and handling events in your applications.
Understanding the Pub/Sub Pattern:
The Pub/Sub pattern is a behavioral design pattern that enables a system to communicate between various components without them being directly aware of each other. In the context of events, the Publisher (the sender) emits events, and Subscribers (listeners) subscribe to specific events of interest. This decoupling ensures a flexible and scalable architecture.
To get started, create a new JavaScript file and set up a basic structure. You can use this as a standalone module or incorporate it into your existing project.
// eventEmitter.js
class EventEmitter {
constructor() {
this.subscribers = {};
}
subscribe(event, callback) {
if (!this.subscribers[event]) {
this.subscribers[event] = [];
}
this.subscribers[event].push(callback);
}
unsubscribe(event, callback) {
if (this.subscribers[event]) {
this.subscribers[event] = this.subscribers[event].filter(sub => sub !== callback);
}
}
emit(event, data) {
if (this.subscribers[event]) {
this.subscribers[event].forEach(sub => sub(data));
}
}
}
// Example Usage
const myEventEmitter = new EventEmitter();
const callback1 = data => {
console.log(`Callback 1 executed with data: ${data}`);
};
const callback2 = data => {
console.log(`Callback 2 executed with data: ${data}`);
};
myEventEmitter.subscribe('customEvent', callback1);
myEventEmitter.subscribe('customEvent', callback2);
myEventEmitter.emit('customEvent', 'Hello, Pub/Sub!');
// Output:
// Callback 1 executed with data: Hello, Pub/Sub!
// Callback 2 executed with data: Hello, Pub/Sub!
myEventEmitter.unsubscribe('customEvent', callback1);
myEventEmitter.emit('customEvent', 'Event after unsubscribing');
// Output:
// Callback 2 executed with data: Event after unsubscribing
Let's break down the code for creating an Event Emitter in JavaScript using the Pub/Sub pattern step by step:
EventEmitter
Class:
constructor() {
this.subscribers = {};
}
The EventEmitter
class has a constructor that initializes an empty object called subscribers
. This object will be used to store events and their corresponding subscribers.
subscribe
Method:
subscribe(event, callback) {
if (!this.subscribers[event]) {
this.subscribers[event] = [];
}
this.subscribers[event].push(callback);
}
The subscribe
method allows subscribers to register their interest in a specific event.
If the specified event does not exist in the subscribers
object, a new array is created for that event. The callback function is then added to the array of subscribers for the given event.
unsubscribe
Method:
unsubscribe(event, callback) {
if (this.subscribers[event]) {
this.subscribers[event] = this.subscribers[event].filter(sub => sub !== callback);
}
}
The unsubscribe
method enables subscribers to unregister their interest in a particular event.
If the specified event exists in the subscribers
object, the method filters out the callback that needs to be unsubscribed from the array of subscribers for that event.
emit
Method:
emit(event, data) {
if (this.subscribers[event]) {
this.subscribers[event].forEach(sub => sub(data));
}
}
The
emit
method triggers the execution of all subscribed callbacks for a given event.If the specified event exists in the
subscribers
object, it iterates through the array of callbacks for that event and executes each callback, passing the provideddata
as an argument.
Example Usage:
const myEventEmitter = new EventEmitter();
const callback1 = data => {
console.log(`Callback 1 executed with data: ${data}`);
};
const callback2 = data => {
console.log(`Callback 2 executed with data: ${data}`);
};
myEventEmitter.subscribe('customEvent', callback1);
myEventEmitter.subscribe('customEvent', callback2);
myEventEmitter.emit('customEvent', 'Hello, Pub/Sub!');
// Output:
// Callback 1 executed with data: Hello, Pub/Sub!
// Callback 2 executed with data: Hello, Pub/Sub!
// now we are unsubscribing the callback1 from 'customEvent',
// callback1 will not be executed any more on this event
myEventEmitter.unsubscribe('customEvent', callback1);
myEventEmitter.emit('customEvent', 'Event after unsubscribing');
// Output:
// Callback 2 executed with data: Event after unsubscribing
An instance of the
EventEmitter
class (myEventEmitter
) is created.Two callback functions (
callback1
andcallback2
) are defined.Both callbacks are subscribed to the 'customEvent' using the
subscribe
method.The
emit
method is used to trigger the execution of subscribed callbacks for the 'customEvent' with the provided data.The
unsubscribe
method is then used to removecallback1
from the subscribers for the 'customEvent'.Finally, another
emit
demonstrates that onlycallback2
is executed after unsubscribingcallback1
.