The Publisher/Subscriber Pattern in JavaScript

Pub/sub, simplified

jsmanifest
Oct 11, 2019 · 4 min read
Image for post
Image for post
Photo by NordWood Themes on Unsplash

In this article, we will be going over the publish/subscribe pattern in JavaScript and see how simple (but powerful) it is to implement in our JavaScript applications.

The publisher/subscriber pattern is a design pattern that allows us to create powerful dynamic applications with modules that can communicate with each other without being directly dependent on each other.

The pattern is quite common in JavaScript and has a close resemblance to the observer pattern in the way it works — except that in the observer pattern, an observer is notified directly by its subject, whereas in the publisher/subscriber method, the subscriber is notified through a channel that sits in-between the publisher and subscriber that relays the messages back and forth.

When we implement this, we will need a publisher, subscriber, and some place to store callbacks that are registered from subscribers.

Let’s go ahead and see how this looks like in code. We’re going to use a factory function (you don’t have to use this pattern) to create the publisher/subscriber implementation.

The first thing we’re going to do is to declare a local variable inside the function to store subscribed callbacks:

function pubSub() {
const subscribers = {}
}

Next, we’ll define the method which will be responsible for inserting callbacks to :

What’s happening here is that before attempting to register a callback listener for an event name, it checks to see if the property in the storage is already an . If it isn't, it assumes that this will be the first registered callback for and initializes it into an array. Then, it proceeds to push the callback into the array.

When the event fires, it will take two arguments:

  1. The
  2. Any that will be passed to *every single callback registered in

Lets go ahead and see how this looks like in code:

Before iterating on the list of callbacks in , it’ll check if it actually exists as an array in the object. If it doesn't, it will assume that the was never even registered before, so it will simply just return. This is a safeguard against potential crashes.

After that, if the program reaches the line, then we know that the was registered with one or more callbacks in the past. The program will proceed to loop through safely.

For each callback that it encounters, it calls the callback with the that was passed in as the second argument.

So this is what will happen if we subscribed a function like this:

function showMeTheMoney(money) {
console.log(money)
}
const ps = pubSub()ps.subscribe('show-money', showMeTheMoney)

And if we call the method sometime in the future:

ps.publish('show-money', 1000000)

Then the callback we registered will be invoked in addition to receiving as the argument:

function showMeTheMoney(money) {
console.log(money) // result: 10000000
}

And that’s how the publisher/subscriber pattern works. We defined a function and provided a location locally to the function that stores the callbacks, a method to register the callbacks, and a method that iterates and calls all of the registered callbacks with any data.

There’s one more problem, though. In a real application, we might suffer a never-ending memory leak if we subscribe many callbacks, and it’s especially wasteful if we don’t do anything about that.

So what we need last is a way for subscribed callbacks to be removed when they are no longer necessary. What often happens in this case is that some method is placed somewhere. The most convenient place to implement this is the return value from because, in my opinion, it’s the most intuitive when we see this in code:

In the example, we needed an index. So we make sure we remove the right one since we used , which needs an accurate index to remove the item we are looking for.

You can also do something like this; however, it’s less performant:

Disadvantages

Although there are huge benefits to this pattern, there are also devastating disadvantages that might cost us a lot of debugging time.

How do we know if we subscribed the same callback before or not? There’s really no way to tell unless we implement a utility that maps through a list, but then we’d be making JavaScript do more tasks.

It also becomes harder to maintain our code the more we abuse this pattern in a real-world scenario. The fact that callbacks are decoupled in this pattern makes it hard to track down each step when you have callbacks doing this and doing that everywhere.

Conclusion

And that concludes this post. I hope you found this to be valuable and look out for more in the future!

Better Programming

Advice for programmers.

Sign up for The Best of Better Programming

By Better Programming

A weekly newsletter sent every Friday with the best articles we published that week. Code tutorials, advice, career opportunities, and more! Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

jsmanifest

Written by

Team Lead Front End Developer for TeleMedicine. Follow and Join Me on my Adventures. https://jsmanifest.com

Better Programming

Advice for programmers.

jsmanifest

Written by

Team Lead Front End Developer for TeleMedicine. Follow and Join Me on my Adventures. https://jsmanifest.com

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store