Event Bus Pattern via Native EventEmmiter Class
Tags: typescript, javascript, patterns, webdev
Published: 2019-11-02 18:59:24

---
title: Event Bus Pattern via Native EventEmmiter Class
published: true
description:
tags: typescript,javascript,patterns,webdev
---

Event Bus is one of the most popular patterns for decoupling parts of your system (components) or anything else that shouldn't be tightly coupled together.
If you have a large scale application with a lot of components interacting with each other, you may want to make your components communicate via intermediary and maintain loose coupling and separation of concerns principles.

In this article, I'm going going to introduce you to [my event bus implementation](https://github.com/ivandotv/estacion) via native Node.js [EventEmitter](https://nodejs.org/api/events.html) class.

## How it works

The point of the event bus pattern is to have components be able to issue updates to their state or request some action to be taken via an intermediary (event bus) so they are completely decoupled from the rest of the system (other components), and because of that they can easily be removed from the system and other components can be easily added.

![event bus simple diagram](https://raw.githubusercontent.com/ivandotv/blog-posts/master/posts/eventbus-in-typescript/assets/event-bus-simple.png)

## Implementation

My implementation of the event bus pattern is not dispatching just simple messages, it has two concepts: `channel` and `topic`.

Event bus can contain any number of **channels**, and every channel can contain any number of **topics**.

You can listen to the `channel` and get notified on any topic on that channel or you can listen to a particular topic and be notified **only** when there are updates on that particular topic.

![channel communication](https://github.com/ivandotv/blog-posts/blob/master/posts/eventbus-in-typescript/assets/event-comm.png?raw=true)

In the above diagram `TODO Component` will ask the event bus to create the channel: `TODO` with topics `added`, `removed` and `updated`.
When the channel is created it is available to be broadcasted on.

Depending on what is going on inside the `TODO Component` at some point the component will ask the event bus to broadcast on the `TODO` channel with various topics.

`Logging Component` wants to notified about everything regarding the `TODO's` (added, updated, removed) so in this case, the component will subscribe itself to the `TODO` channel directly (no need to subscribe to each topic individually).

`Component X` only wants to know when todos are `removed` so it will listen to (subscribe to) only to the `removed` topic on the `TODO` channel.

`Component Y` will subscribe only to the `updated` topic on the `TODO` channel.

### Event

Every listener receives the event with these properties

```js
const event = {
    channel:'TODO', // channel name
    topic:'removed' // topic name
    payload:{ // custom object with your custom payload (data)
        anyting:'you want'
    }
}
```

Let's create the previous diagram in code:

```js
const { EventBus } = require("estacion")
// or import { EventBus } from 'estacion'

// create the event bus
const bus = new EventBus()

// create the channel
const todoChannel = bus.channel("TODO")

// create topics on the channel (optional)
const todoCreatedTopic = todoChannel.topic("created")
const todoUpdatedTopic = todoChannel.topic("updated")
const todoRemovedTopic = todoChannel.topic("removed")

// create listeners
// logingComponent ( in this case just a simple function)
const loggingComponent = event => {
  console.log(event.channel) //channel name: TODO
  console.log(event.topic) // topic name: removed OR added or UPDATED
  console.log(event.payload) // custom payload (data) from the event
}

const componentX = event => {
  console.log(event.channel) // TODO
  console.log(event.topic) // removed only !
  console.log(event.payload) // custom payload from the event
}

const componentY = event => {
  console.log(event.channel) // TODO
  console.log(event.topic) // updated only !
  console.log(event.payload) // custom payload from the event
}

// Connect listeners to the appropriate channel or topic

// add loggingComponent directly to the channel
todoChannel.addListener(loggingComponent)

// add componentX only to the "removed" topic
todoRemovedTopic.addListener(componentX)
// or get to the topic from the channel
todoChannel.topic("removed").addListener(componentX)

// add componentY only to the "updated" topic
todoUpdatedTopic.addListener(componentY)
// or get to the topic from the channel
todoChannel.topic("updated").addListener(componentY)

// emit when todo is removed
todoRemovedTopic.emit({ id: "3413241" })
// or
todoChannel.topic("removed").emit({ id: "3413241" })

// emit when todo is created
todoCreatedTopic.emit({
  id: "3413241",
  title: "Buy Milk",
  content: "Lorem Ipsum"
})
```

## Conclusion

- You can have any number of event bus instances, channels and topics.
- Easily create and remove channels and topics (all listeners are automatically unsubscribed when channel or topic is destroyed)

It can be used in the browser via [events](https://www.npmjs.com/package/events) module which is automatically included by the bundlers like webpack and browserify.

This is just a simple, minimal demo to get you started with the event bus. This event bus module is written in TypeScript and it has everything you need to manage your events.

Head over to the [repository](https://github.com/ivandotv/estacion) for more examples and in-depth explanations.

Or download from [npm](https://www.npmjs.com/package/estacion)