How and Why JZ Publish / Subscribe Should Be Used

If you don’t already know, JZ Publish/Subscribe is a jQuery plugin that I developed to add a simple, but powerful Pub/Sub feature to the jQuery utility functions. I’m guessing there are some people out there who don’t understand what Pub/Sub is, how to use it, or why to use it. I’m here to bring some answers and give a specific example of how JZ Publish/Subscribe can be used.

What is Publish/Subscribe?

The first thing that should be done is help you understand what the Pub/Sub pattern really is and how it works. If you already know what the Observer pattern is (or already know what Pub/Sub is, for that matter) then you know what Pub/Sub is all about and you can move on to the next section. Both of these patterns allow you to observe/subscribe to certain events. When the event happens (or get published), then some code that you specified is run in response to that event. It really is that simple. If you’ve ever used event listeners on HTML elements before, then you have already used this pattern.

The biggest difference between event listeners or the standard observer pattern and my implementation of Pub/Sub is that my subscriptions listen for a _global _event, whereas the event listeners are added directly to the DOM elements and listen only for events for that object. There are pros and cons to each approach. The global Pub/Sub allows for greater decoupling, whereas the normal event listener makes it clearer as to exactly what events we’re listening for and won’t cause problems caused by two different events having the same name.

How to Use JZ Publish/Subscribe

I’m going to show an example that uses JZ Publish/Subscribe in order to answer both of the questions at the same time. This example will be a simple widget that display the latest Twitter posts from my Twitter account. You can view the live demo here. Demo Page has been removed due to Twitter API changes. Code samples below will also be out of date.

We’ll start off by creating the HTML document where the widget will reside. It’s quite simple. All we need within the document is a button that refreshes the widget with the latest posts and a container for all of the tweets. Also, we can’t forget to get the JavaScript libraries we all depend on.

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Twitter Widget</title>
</head>
<body>
<button class="refresh-button">Refresh</button>
<div class="twitter-widget"></div>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.pubsub.min.js"></script>
</body>
</html>

Now we’ll create a model, or an object that stores and retrieves the tweets. Here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var model = ({
init: function() {
$.subscribe('update-tweet-data', this.getTweets, this);
return this;
},
getTweets: function() {
// get tweets from twitter via JSONP Ajax
$.getJSON('http://search.twitter.com/search.json?q=from:joezimjs&callback=?', function(data){
// If we got some results, assign the data to this.data, otherwise, just keep the data as is
this.data = data && data.results || this.data;
// Publish that we have tweets ready to be used
$.publish('tweet-data-changed', this.data);
});
},
data: []
}).init(); // Initialize the model

Here we get to see our first bits of Pub/Sub. In the init function we subscribe to the “update-tweet-data” topic (for this plugin, events are called topics) and telling it to call the getTweets function when that topic is published. Notice that inside getTweets we cannot use the keyword this in order to refer to the model object, because the plugin calls the function in a different context. I realize that for many people this can be a nuisance, and it has already proven to be a nuisance to me, so in the next version of JZ Publish/Subscribe I will add the ability to pass in a context to run the function from.

Now if you look inside the callback for the AJAX request you’ll see a $.publish call. This informs anyone subscribed to that topic that the model now has new tweet data so they can respond accordingly. The view is the object that will respond, and it is also the next bit of code to show.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var view = ({
init: function() {
$.subscribe('tweet-data-changed', this.displayTweets);
// bind a click to the refresh button to publish 'gettweets', then click it right away to get the first batch of tweets.
$('.refresh-button').on('click', '', this.refresh).trigger('click');
return this;
},
displayTweets: function (topic, data) {
var len = data.length,
i = 0,
// Remove the widget from the DOM and clean it out
$wgt = $('.twitter-widget').detach().empty();
// Go through each tweet and append them into the widget
for(; i<len; i++){
var data_i = data[i],
tweeter = data_i.from_user,
tweetText = data_i.text;
tweetText = tweetText.replace(/http:\/\/\S+/g, '<a href="$&" target="_blank">$&</a>')
.replace(/(@)(\w+)/g, ' $1<a href="http://twitter.com/$2" target="_blank">$2</a>')
.replace(/(#)(\w+)/g, ' $1<a href="http://search.twitter.com/search?q=%23$2" target="_blank">$2</a>');
$wgt.append('<div class="tweet"><a href="http://twitter.com/'+tweeter+'" target="_blank"><img src="'+data_i.profile_image_url+'" class="tweet-image" /></a>'+tweetText+'</div>');
}
// re-attach the widget to the DOM
$('body').append($wgt);
},
refresh: function() {
// Publish that we want tweets
$.publish('update-tweet-data');
}
}).init(); // Initialize the view

Once again we set up our subscriptions in the init function. Notice the next line though. We set up an onclick handler for the refresh button that just publishes the ‘update-tweet-data’ topic, which is what the model is subscribed to. Here’s the fun part, we also immediately trigger a click event on the button in order to get the initial tweets.

The next method is displayTweets, which is called when the model publishes the ‘tweet-data-changed’ topic right after it has finished retrieving the tweets. As you might expect by the name, this function uses the data to create the HTML to display all of the tweets in the widget container.

Why We Needed JZ Publish/Subscribe

I’m sure there are some of you who wonder why on earth we bothered using the Pub/Sub pattern at all in this example. I agree that if you knew with 100% certainty that this is the only code you needed and weren’t going to add to it at all, then it was maybe only slightly useful for organization’s sake, however, the time this tends to shine is later when you want make some additions.

Let’s pretend that this widget is in your sidebar, but now you also want to make a page that features your twitter posts. Instead of writing an entirely new model and view, we only need a new view. For the new view, we can just remove the refresh button’s click handler and the refresh method (which I only put in there as a method instead of an anonymous function for testing purposes), then change whatever we want to change with the DOM and HTML related code.

Normally, even if we did just add a new view, without the Pub/Sub pattern involved, you would need to update the model to also call the displayTweets function for the new view, which would then break on any page that didn’t have the new view, unless you made the model observable, which would require a bit of work.

Using Pub/Sub decouples the model and view from each other. The view has no idea the model exists and vice versa, which makes for better scaling, as I explained above. The Pub/Sub pattern is very nice for keeping code organized and decoupled for large applications or even just for applications that might grow. If you’re going to be doing things like this a lot with large applications, I’d actually recommend Backbone.js, which gives a great framework for organizing your code and using the Pub/Sub pattern.

Wrapping Things Up

Amazingly, even when I’m writing posts that aren’t in the JavaScript Design Patterns series, I still end up writing about design patterns. I even brought up the Observer pattern, which is next up on the list for the JavaScript Design Patterns. The best part is that it wasn’t even intentional. Well, now you got a slight preview of the Observer patter and its usefulness, but you still shouldn’t skip reading the post about it; there’s still plenty more to learn about it.

I hope that this has given you a bit of an overview of how to use JZ Publish/Subscribe and also made you consider using it if you haven’t already. Even if you don’t use my plugin, I hope you learned the value of the Pub/Sub pattern and use it to your advantage. Seriously, I’d rather have everyone writing better code than using my plugin. As always, feel free to leave comments or share this with your friends and Happy Coding!

Author: Joe Zimmerman

Author: Joe Zimmerman Joe Zimmerman has been doing web development ever since he found an HTML book on his dad's shelf when he was 12. Since then, JavaScript has grown in popularity and he has become passionate about it. He also loves to teach others though his blog and other popular blogs. When he's not writing code, he's spending time with his wife and children and leading them in God's Word.