Implement Publish Subscribe Pattern in jQuery
The publish/subscribe (Pub/Sub) messaging pattern enables decoupled communication between different components of a web application. This guide demonstrates how to implement a lightweight, custom Pub/Sub system using jQuery's built-in event handling mechanism—specifically relying on an empty jQuery object as a central event bus.
The Core Concept
jQuery includes a robust custom event system designed for DOM
elements via the .on(), .off(), and
.trigger() methods. Because jQuery can wrap plain
JavaScript objects just like DOM elements, you can use a plain object
wrapped in jQuery as an event aggregator without attaching events to
actual HTML nodes.
Creating the Pub/Sub Object
You can create a standalone Pub/Sub module in just a few lines of code:
const PubSub = (function($) {
const bus = $({});
return {
subscribe: function(topic, handler) {
bus.on(topic, function(event, ...args) {
handler(...args);
});
},
unsubscribe: function(topic, handler) {
bus.off(topic, handler);
},
publish: function(topic, data) {
bus.trigger(topic, [data]);
}
};
})(jQuery);How to Use the Implementation
1. Subscribing to Events
To listen for a specific event or message, use the
subscribe method. You define the topic name and pass a
callback function to handle the data:
function onUserLogin(userData) {
console.log(`User logged in: ${userData.username}`);
}
// Subscribe to the 'user:login' topic
PubSub.subscribe('user:login', onUserLogin);2. Publishing Events
When a notable action occurs elsewhere in the application, publish the event along with any relevant payload:
// Trigger the event with an associated data payload
PubSub.publish('user:login', {
username: 'john_doe',
timestamp: Date.now()
});3. Unsubscribing from Events
To clean up memory or stop listening for notifications, unsubscribe from the topic using the original callback reference:
// Remove the listener
PubSub.unsubscribe('user:login', onUserLogin);Passing Multiple Arguments
To send multiple parameters during an event broadcast, pass an array
to bus.trigger():
// Publisher
PubSub.publish = function(topic, ...args) {
bus.trigger(topic, args);
};
// Publishing multiple values
PubSub.publish('cart:update', productId, quantity, total);
// Subscriber receiving multiple values
PubSub.subscribe('cart:update', function(productId, quantity, total) {
console.log(`Cart updated: Product ${productId}, Qty: ${quantity}, Total: $${total}`);
});Using this approach eliminates direct dependencies between UI components, asynchronous network calls, and data models, resulting in cleaner and more maintainable code.