DEV Community

Meysam Faghfouri
Meysam Faghfouri

Posted on

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.

Top comments (0)