PubSub with Javascript in 5 minutes or less
Tags: pubsub, javascript, javascriptclasses, publishersubscriber
Published: 2019-08-04 22:43:54

---
title: PubSub with Javascript in 5 minutes or less
published: true
description: A basic implementation of Publisher Subscriber model to understand underlying logic of PubSub and events 
tags: PubSub, Javascript, Javascript-classes, Publisher-Subscriber
cover_image: https://qph.fs.quoracdn.net/main-qimg-1726faa797a20c47cb72ec8ed37af317.webp
---

## Let's begin

*Ok, first things first. I am not a 10xer or pro at patterns so if there is any discrepancy, please correct me. This will only improve my and your understanding of the concept.*
With that little disclaimer out of the way, let's dig in.

## Introduction

You might have heard the term *PubSub* being thrown around alot (especially since Angular made Reactive pattern/event-driven pattern famous in front-end world) or maybe you just stumbled here by accident. Either way, if you are wondering what this PubSub mumbo-jumbo is, this post will help you understand the concept a little better, along with a basic implementation with VanillaJS (Sorry I really love things simple!).

## What is PubSub?

PubSub or Publisher-Subscriber model is a concept which basically involves two ends. *Publisher* and *Subscriber*. Or in very simple terms: **Giver** and **Taker**. This should tell you something about flow of data in the pattern. Yup, that is right. Publisher will have some data it needs to give (*let's not worry about where it got that from right now*) which Subscribers take and may: 
 * display, 
 * manipulate, 
 * post-process or 
 * do black magic with. 
I don't know, that's not really my concern. 

Well what if the data is not needed by just one person/receiver. Maybe it's a common thing that many people want. Let's say, you are driving down Route 666 and there is a crash 500 metres down. It's unlikely that it's just you alone on 666 (if you are, good luck!), there maybe few others driving along. Imagine how useful this information would be to all of them. Right? Now, let's suppose before getting on Route 666, all of you signed up for this service that gives you updates about *events* happening along Route 666 until you get off the highway(unsubscribe). So now, all of the people who signed up are *Subscribers* and your service-provider who you signed up with is your *Publisher*. Notice how the word **event** got in there? Well the information is usually sent by Publisher after some "event"(occurs). PubSub is not one-off model. Usually it's an ongoing process. Anyway you get the gist, right? So what did we find out?

![PubSub Model](https://thepracticaldev.s3.amazonaws.com/i/yprblc0nxdzqp78ekfbr.png)
<figcaption>PubSub Model</figcaption>

## Discovery

1. PubSub has two ends: Publisher (Giver) and Subscriber (Taker).
2. PubSub talks in terms of events.
3. PubSub has single Publisher (origin of events) and multiple subscribers(culmination of events).
4. PubSub is on-going model rather than one-off. (You receive events overtime).
4. You sign-up (subscribe) to receive information and sign-off (unsubscribe) to stop receiving further information.

Now let's take these concepts and create a basic working model with good ol' Javascript.
I'll be using ES6 class with private members workaround (Javascript ES6 doesn't natively support `private`).

## Code Example
First let us build the barebones structure of our Publisher-Subscriber module. We will take a `class` based approach which will contain all the pubsub logic as well as any data structure needed. The list below illustrates what we need to accomplish and then we'll build out a barebones structure from that.
### Requirements
0. Some event (fake) source to generate data. (In real world this might generate from real-world events but for the purposes of this example, we'll fake it).
1. Something to hold our subscriber list so that we know who we need to send data to (Data).
2. Someway to register/deregister subscribers (Methods).
3. Someway to send data to all the subscribers (Logic).

### Barebones
#### Data
To store metadata in our PubSub model, we'll use following variables:
1. `private eventSourceAddress`: In real world, this would be your WebSockets, Server Sent events or any other real-time source address. We will just initialize it in our code and not connect to actual backend. 
2. `private subscribers`: Object array to hold our subscriber list. You are very welcome to find out more optimal method, but that is not the focus of this article.

#### Methods
1. `private _addSubscriber()`: Adds subscriber to the list.
2. `private _removeSubscriber()`: Removes subscriber from the list.
3. `private _removeAllSubscribers()`: Clears out the subscriber list.
4. `public subscribe()`: Available to instantiated class that internally calls `_addSubscriber`.
5. `public unsubscribe()`: Available to instantiated class that internally calls `_removeSubscriber`.
6. `public unsubscribeAll()`: Available to instantiated class that internally calls `_removeAllSubscribers`.

#### Logic
1. `private _pushPayloadToSubscribers()`: Pushes data to all subscribers.

#### Additional methods
Since we will faking event source, we need additional data and methods to enable that. These are not part of actual Publisher-Subscriber model.
##### Data
1. `private __tick`: Holds the current reference to event source (timer).

##### Method
1. `private __tickHandler()`: Executed after certain interval to send data to publisher.
2. `public plugSource()`: Plug in event source and start feed.
3. `public unplugSource()`: Unplug event source and stop feed.

Ok, looks like we have all the ingredients ready, now let's go ahead and build our PubSub model.

### Implementation
```javascript
const PubSub = (function(){
    // private variables and data
    return class _PubSubInternal{
        // public methods and data
    }
})();
```

What the hell was that?

Sorry, as I said, Javascript natively doesn't support `private` accessors, we have to use this little workaround to have "private" variables in our class. What we are doing is using [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) and [Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures).
The outer function executes immediately as the script is processed and the function inside it gets called and it returns `_PubSubInternal`.
Since we are returning `_PubSubInternal` from inside the function, all the variables and methods declared inside the function will be accessible to this returned class (but not to instantiated object of this class). This is called closure. Pretty cool, right?!

> Javascript is pretty awesome!

Anyway, moving on.

```javascript
    const PubSub = (function(){
        // private variables and data
        let eventSourceAddress;
        let subscribers;
        let __tick;

        function __tickHandler() {
            _pushPayloadToSubscribers(new Date());
        }

        function _pushPayloadToSubscribers(payload) {
            subscribers.map(subscriber => {
                subscriber.callback(payload);
            });
        }

        function _addSubscriber(callback) {
            var id = new Date().getTime();
            subscribers.push({ id, callback });
            return id;
        }

        function _removeSubscriber(id) {
            subscribers = subscribers.filter(subscriber => subscriber.id !== id);
        }

        function _removeAllSubscribers() {
            subscribers = [];
        }

        return class _PubSubInternal{
            // public methods and data
            constructor(address) {
                eventSourceAddress = address;
                subscribers = [];
                __tick = null;
            }

            plugSource() {
                console.log("Event feed attached!");
                __tick = window.setInterval(__tickHandler.bind(this), 4000);
            }

            unplugSource() {
                window.clearInterval(__tick);
                console.log("Event feed unplugged!");
            }

            subscribe(callback) {
                return _addSubscriber(callback);
            }

            unsubscribe(id) {
                return _removeSubscriber(id);
            }

            unsubscribeAll() {
                return _removeAllSubscribers();
            }
        
        }
    })();
```
And that is it. This completes our implementation of our Publisher-Subscriber model. 

## Run it
```javascript
var pubSub = new PubSub(someEventSourceAddress);

// add subscribers
let subscriber1 = pubSub.subscribe( (data) => {
    console.log("Consoling from Subscriber 1");
    console.log(data);
});

let subscriber2 = pubSub.subscribe( (data) => {
    console.log("Consoling from Subscriber 2");
    console.log(data);
});

// Start fake feed
pubSub.plugSource();

```
We instantiated our `PubSub` to `pubSub` variable which holds reference to `PubSub` object. `subscriber1` and `subscriber2` hold the `Resource ID` of their subscription (subscription id) which can be used later on to unsubscribe. Callbacks get executed whenever new data is pushed to these subscriber. The sample output is below.
```
// Output

// subscriber 1 subscribed
// subscriber 2 subscribed
> Event feed attached!

// after 4 secs
> Consoling from Subscriber 1
> Sun Aug 04 2019 17:44:44 GMT-0400 (Eastern Daylight Time)

> Consoling from Subscriber 2
> Sun Aug 04 2019 17:44:44 GMT-0400 (Eastern Daylight Time)
...
...
```

To stop subscription and feed, just do:
```javascript
pubSub.unsubscribe(subscriber1);
pubSub.unsubscribe(subscriber2);
// OR
pubSub.unsubscribeAll();

// Stop feed
pubSub.unplugSource(); // Event feed unplugged!
```

And that is it folks! Hope you enjoyed the article and learned something new :)

You can tinker around with the implementation on codesandbox
{% codesandbox optimistic-lumiere-nzlmu %}

Good luck!