DEV Community

Meysam Faghfouri
Meysam Faghfouri

Posted on

7

publish/subscribe pattern in javascript

There are a lot of design patterns in programming world and each of them has been invented to solve some specific problems which we may face with during coding.

One of the interesting of them is 'publish/subscribe' pattern that gives us the ability to separate different module/component from each other and send/receive messages from them without any tightly coupled relation or even needing to know about each other.

I implemented a very simple library in javascript by using above concept and definition and I think it can be used as something like a little state management in component-based applications and I would like to share my experience and understanding with all of you

note: I know there are a lot of powerful libraries to do state management and pub/sub pattern but I believe that creating something based on concepts can help us to learn and understand it deeply :)

so let's start it.

First of all, we need a central object to register our subscribers or remove them from the list of subscribers and decide which subscribers should receive the messages when a publisher sends a message. also, we need to define our methods and subscribers' holder as static because we don't want to create a new one of this central object whenever we want to use it.
something like this:

var PubSub = (function () {
    function PubSub() {
    }
    PubSub.subscribe = function (eventName, func) {
        this.initDic(eventName);
        this.dic[eventName].push(func);
    };
    PubSub.unsubscribe = function (eventName, func) {
        this.initDic(eventName);
        this.dic[eventName] = this.dic[eventName].filter(function (x) { return x != func; });
        if (!this.dic[eventName].length) {
            delete this.dic[eventName];
        }
    };
    PubSub.publish = function (eventName, data) {
        this.initDic();
        if (this.dic[eventName])
            for (var _i = 0, _a = this.dic[eventName]; _i < _a.length; _i++) {
                var func = _a[_i];
                func(data);
            }
    };
    PubSub.initDic = function (eventName) {
        if (!this.dic) {
            this.dic = {};
        }
        if (eventName && !this.dic[eventName]) {
            this.dic[eventName] = [];
        }
    };
    PubSub.dic = null;
    return PubSub;
}());

Then imagine we have two object called customer and manager and the customer wants to listen to a special event like this:

const pubsub = require('./PubSub');

const customer = function(name) {
    this.name = name;

    function emailReceiver(data) {
        alert(`${this.name} -- I received an email from ${data.sender}, content: ${data.content}`);
    }
    PubSub.subscribe(`receiveEmail${this.name}`, emailReceiver.bind(this));
}

const manager = function(name) {
    this.name = name;

    this.sendMessage = (customerName, content) => {
        PubSub.publish(`receiveEmail${customerName}`, {
            sender: this.name,
            content: content
        });
    }
}

And the manager wants to send an email to a specific customer like this:

let jack = new customer('Jack');
let eli = new customer('Eli');

let manager1 = new manager('Boss');

manager1.sendMessage('Jack', 'you should prepare a report until tomorrow!');
manager1.sendMessage('Eli', 'call me!');

I've created a JSFiddle and you can see the result

That's it! I hope it helps you to better understand the basic concept of this pattern.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more