# Design patterns in Javascript: Publish-Subscribe or PubSub

What's a design pattern in software engineering? It's a **general repeatable solution** to a commonly occurring problem in software design. In this article, we'll be looking at one of such common design patterns and see how it can be put to use in real world applications.

This pattern is referred to as Publish-Subscribe or PubSub. Let's start with the overall notion behind this pattern before writing some code.

## Overview

![pubsub.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631540738187/qmkcqTo2D.png)


The image above describes the general idea behind this pattern:
- We have a PubSub 'container' that maintains a list of `subscribers` (a subscriber is just a function)
- A new subscription can be created by using the `subscribe(subscriber)` method, which essentially adds the `subscriber` into our PubSub container
- We can use `publish(payload)` to call all the existing `subscribers` in the PubSub container with `payload`
- Any specific `subscriber` can be removed from the container, at any point in time, using the `unsubscribe(subscriber)` method.

## Implementation
Looking at the points above it's pretty straightforward to come up with a simple implementation:

```javascript
// pubsub.js

export default class PubSub {
  constructor(){
    // this is where we maintain list of subscribers for our PubSub
    this.subscribers = []
  }
  
  subscribe(subscriber){
    // add the subscriber to existing list
    this.subscribers = [...this.subscribers, subscriber]
  }
  
  unsubscribe(subscriber){
   // remove the subscriber from existing list
    this.subscribers = this.subscribers.filter(sub => sub!== subscriber)
  }
  
  publish(payload){
   // publish payload to existing subscribers by invoking them
    this.subscribers.forEach(subscriber => subscriber(payload))
  }
}
```

Let's add a bit of error handling to this implementation:
```javascript
// pubsub.js

export default class PubSub {
  constructor(){
    this.subscribers = []
  }
  
  subscribe(subscriber){
    if(typeof subscriber !== 'function'){
      throw new Error(`${typeof subscriber} is not a valid argument for subscribe method, expected a function instead`)
    }
    this.subscribers = [...this.subscribers, subscriber]
  }
  
  unsubscribe(subscriber){
    if(typeof subscriber !== 'function'){
      throw new Error(`${typeof subscriber} is not a valid argument for unsubscribe method, expected a function instead`)
    }
    this.subscribers = this.subscribers.filter(sub => sub!== subscriber)
  }
  
  publish(payload){
    this.subscribers.forEach(subscriber => subscriber(payload))
  }
}

```

## Usage
We can use this implementation as follows:

```javascript
// main.js
import PubSub from './PubSub';

const pubSubInstance = new PubSub();

export default pubSubInstance
```

Now, elsewhere in the application, we can publish and subscribe using this instance:
```javascript
//app.js
import pubSubInstance from './main.js';

pubSubInstance.subscribe(payload => {
  // do something here
  showMessage(payload.message)
})
```

```javascript
// home.js
import pubSubInstance from './main.js';

pubSubInstance.publish({ message: 'Hola!' });
```

## Is it useful in real applications?
Yes. In fact, there are many libraries that use it under the hood and you may not have realized it so far.  Let's take the example of the popular state management library for ReactJS - **Redux**. Of course, its implementation is not as simple as ours, since it's been implemented to handle many other nuances and use-cases. Nevertheless, the underlying concept remains the same.

Looking at the [methods offered by Redux](http://redux.js.org/docs/api/Store.html#store-methods), You would see `dispatch()` and `subscribe()` methods which are equivalent to `publish()` and `subscribe()` methods we implemented above. You usually won't see `subscribe()` method getting used directly, this part is abstracted away behind `connect()` method offered by react-redux library. You can follow the implementation details [here](https://github.com/reduxjs/react-redux/blob/4.x/src/components/connect.js#L199) if that interests you. 

In summary, all react components using `connect()` method act as subscribers. Any component using `dispatch()` acts as the publisher. And that explains why dispatching an action from any component causes all `connected` components to rerender. 

## What's next
- We'll see how the idea behind PubSub can be extended further to build a state management library like redux from scratch.
- We'll also see how an Event Emitter can be built from scratch, using similar notion as PubSub

%%[message]
