What is Pub/Sub?
The primary purpose of this model is to provide a way of both triggering and listening for global or semi-global events. There are many libraries that do this: PubSubJS, jQuery has it built in, There are basic examples on the web, etc. These are all good, but it’s important to understand whats happening to the the most out of your events.
When and why should I use it?
The best use of the this model is when you have multiple areas of your application that need to know about an event. For example:
- An AJAX request has been made (to show an activity indicator)
- An request error has happened (show an error on the page)
- User has clicked the window (for popup hiding)
- User has or will log in / log out (for cleanup)
- Most window level events
When not to use it?
This model is not the best choice when you want to have consequences for actions (you should use Promises or callbacks) or when you need to guarantee delivery / receipt of a message (you will need a more complex event manager). For example:
- When you need feedback on the operation (AJAX request → display data on screen)
- When operations need to chain (e.g. A → B → C)
Here is a very basic Pub/Sub model:
What this will do is create a object `events` that allows you “subscribe” to a named event `var e = events.subscribe(‘topic’, callback)`, and it will return an object that will allow you to unsubscribe from the event `e.unsubscribe()`. Additionally anywhere else in your code you can publish an event `events.publish(‘topic’, data)` and all listeners will hear it. An example I like to use for use of this simple event model is showing a global error message whenever a HTTP request fails. (For this example I’m using qwest as my ajax library and I’m monkey patching it. I’m using ES6 syntax in this example).
Note: You should keep monkey patching to a minimum in your applications. It can make your code very hard to debug later if used excessively. What this allows is that whenever a catch condition fires on a qwest request we fire an event and we can listen for it on the page level `events.subscribe(”, displayGlobalError)`.
With this system you can get a simple model that will support small to medium sized sites with a very minimal pub/sub implementation.
As you start using this model a little more you’ll find that you will end up publishing for the same event multiple times to his separate listeners. e.g. `action` and `save` for a user hitting a save button to both show a global “saving” and another more generic event `action` so that we can cancel any items on the page waiting on an action.
In this case it would be helpful to have an event `action.save` so that we can do tiered actions that will trigger both `action` and `action.save`. Additionally you could add the ability to trigger unrelated actions with an event like: `save,profile-change`. So for this advanced ability we would add in some additional flow to our above events object.
With this we can use commas or dots to publish to multiple subscribers.
Any advanced implementation of a this type of model becomes project specific, you can very easily add in things like automatic logging, automatic error reporting and even adding things like one time events or limited use events, but these always end up being project specific.
When using this model the primary thing to work watch out for is not cleaning up events `e.unsubscribe()`. Your events will live in this events object forever and do not automatically get cleaned up. In the case of React every time the object is created it’ll add an event to the object, and if you don’t remove it you’ll end up holding the entire react object in memory for the duration of the app; this can be __very__ bad for memory usage.
And special thanks to Rob McDiarmid for his contributions to the article.
Learn more about BrainStation’s web development course.