Musings by @thedevel

Pub/Sub in JavaScript

527 words · 13 Aug 2011

I recently wrote a post about sprinkling various controller-esque functionality in Backbone Collections for acting as the event hub for the items within their respective collections. The one caveat to the example presented is the tight-coupling that the Domain, SubDomain, and Concept have to AppState. While implementing this (in my real project), I became frustrated with needing to specify which objects needed to bind to other objects. The other issue with binding to specific objects and loading data asynchronously from the server is needing to include the event binding (or worse initialization) of objects within AJAX success callbacks of dependent objects. Again, tight-coupling.

During my time of frustration I had stumbled upon the PubSubHubbub protocol project page which led me to read up about the Publish/Subscribe messaging pattern in general. The pattern is quite simple:

  • Publishers publish content
  • Subscribers subscribe to content

But, wait?! That sounds a lot like binding (subscribing) and triggering (publishing) events?

Yes it is similar, but with one exception, subscribers and publishers are completely (and intentionally) unaware of each other. This is accomplished by having a central Hub that publishers can publish their content to and subscribers can subscribe to various content feeds. Let us modify the points:

  • Publishers publish content to the Hub
  • Subscribers subscribe to topics or feeds provided by the Hub
  • The Hub pushes new content out to it's subscribers as it receives it from publishers

Having this central hub_ ensures loose-coupling between various objects that depend on or otherwise may respond to actions invoked by other objects._ This solves the first problem mentioned above, but what about managing asynchrony? One of the known disadvantages with a vanilla pub/sub architecture is it's requirement for subscribers to be online virtually all the time to receive incoming published content. Thus, if a subscriber does go offline, any content published during that time will be missed by the subscriber.

Having a dedicated central hub also gives it the optional capability of queuing published content per topic or feed. This allows for offline or late subscribers to receive published content retroactively from the feed's queue. What this means in JavaScript terms is that subscribers can subscribe to content before or after publishers begin publishing content, thus mitigating the asynchrony issue.

Naturally after learning all of this and listening to a podcast on PubSubHubbub, I felt the urge to write a pub/sub library for JavaScript. A common implementation referenced by many is one written by Peter Higgins. While simple and clean, it does not have support queuing content.

I wrote a bit more powerful implementation which supports queues and thus late subscribers. It also has support for undoing/redoing content pushes. As first glance, that may sound a bit weird and unnecessary (which to some extent I agree), but it flowed while writing it. I intend to break out the undo/redo API as a separate branch for those who do not need or are uninterested of that extra layer.

Take a look at the repo on GitHub: https://github.com/bruth/pubsub and the annotated source code http://bruth.github.com/pubsub/docs/pubsub.html