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.