Strict Standards: Declaration of Walker_Page::start_lvl() should be compatible with Walker::start_lvl($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 584

Strict Standards: Declaration of Walker_Page::end_lvl() should be compatible with Walker::end_lvl($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 584

Strict Standards: Declaration of Walker_Page::start_el() should be compatible with Walker::start_el($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 584

Strict Standards: Declaration of Walker_Page::end_el() should be compatible with Walker::end_el($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 584

Strict Standards: Declaration of Walker_PageDropdown::start_el() should be compatible with Walker::start_el($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 603

Strict Standards: Declaration of Walker_Category::start_lvl() should be compatible with Walker::start_lvl($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 702

Strict Standards: Declaration of Walker_Category::end_lvl() should be compatible with Walker::end_lvl($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 702

Strict Standards: Declaration of Walker_Category::start_el() should be compatible with Walker::start_el($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 702

Strict Standards: Declaration of Walker_Category::end_el() should be compatible with Walker::end_el($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 702

Strict Standards: Declaration of Walker_CategoryDropdown::start_el() should be compatible with Walker::start_el($output) in /home/narcvs/blog.narcvs.com/wp-includes/classes.php on line 727

Strict Standards: Redefining already defined constructor for class wpdb in /home/narcvs/blog.narcvs.com/wp-includes/wp-db.php on line 58

Deprecated: Assigning the return value of new by reference is deprecated in /home/narcvs/blog.narcvs.com/wp-includes/cache.php on line 99

Strict Standards: Redefining already defined constructor for class WP_Object_Cache in /home/narcvs/blog.narcvs.com/wp-includes/cache.php on line 404

Deprecated: Assigning the return value of new by reference is deprecated in /home/narcvs/blog.narcvs.com/wp-includes/query.php on line 21

Deprecated: Assigning the return value of new by reference is deprecated in /home/narcvs/blog.narcvs.com/wp-includes/theme.php on line 576
ajaxlights » Blog Archive » Decoupling Data and UI: PubSub

Decoupling Data and UI: PubSub

November 26th, 2008

This is a summary of my presentation today at the sf javascript meetup #4 on maintainable front end architecture in javascript. The presentation involves a demo app and a progressive construction of the model’s subscribe method, which contains the meat of the functionality and interesting javascript.

Demo app:

Demo of the PubSub library - an email client

Decoupling Data and UI in webapps with PubSub patterns

As web applications become more powerful, they grow in complexity. Front end programming patterns and best practices are becoming more and more important both for the community and for the industry.

If you decouple your application’s data and UI layers, you will be able to easily extend and develop one layer without affecting the other. A powerful pattern that allows for such decoupling is publication/subscription.

It turns out that javascript’s combination of functional programming and the ability to apply a scope at runtime makes it a wonderful language to write a PubSub library in. 25 lines of code is enough to create a highly versitile model with both dynamic scoping and currying/partial application. We’ll go through that code together in a moment.

If you look at the application code (not more than some 70 lines), then you notice that the UI and the data layers are completely independent - i.e. they don’t reference each other. All the message passing between the data and the UI are taken care of with code like this:

pubSubBroker.subscribe('email-open', gData, 'onRead');
pubSubBroker.subscribe('email-open', gUI, 'markEmail', true);
var email = {title:'Test email', id:1, body:'Test body'};
//This will call both gData.onRead(email) and gUI.markEmail(true, email);
pubSubBroker.publish('email-arrive', email);

The pubSubBroker creation and publish are both pretty straight forward:

// Our publication and subscription broker
function PubSubBroker() {
  var signals = arguments;
  this.subscribers = {};
  for (var i=0; i < signals.length; i++) {
    this.subscribers[signals[i]] = [];
  }
}

PubSubBroker.prototype.publish = function(signal) {
  var args = Array.prototype.slice.call(arguments, 1)
  for (var i=0; i < this.subscribers[signal].length; i++) {
    var handler = this.subscribers[signal][i];
    handler.apply(this, args);
  }
}

However, the subscribe method is the fun part. Let’s go through its creation step by step in order to understand how we get to the final, slightly non-trivial 7-line implementation. First, we just want the ability to subscribe to signals with a function handler:

PubSubBroker.prototype.subscribe = function(signal, handler){
  this.subscribers[signal].push(handler);
}

Then we add the ability of specifying the scope in which the handler will run on when a signal is published. Use handlerName rather than handler directly, and use call to run the handler in the given scope.

PubSubBroker.prototype.subscribe = function(signal, scope, handlerName){
  this.subscribers[signal].push(function(eventArguments){
    scope[handlerName].call((scope || window), eventArguments);
  });
}

The third version adds the ability to pass in a variable number of arguments to publish. Using apply rather than call allows for this.

PubSubBroker.prototype.subscribe = function(signal, scope, handlerName){
  this.subscribers[signal].push(function(){
    scope[handlerName].apply((scope || window), arguments);
  });
}

Finally, we make currying possible, which allows for partial application that can be super useful in many cases (let me know if you want a useful example and I’ll add it):

PubSubBroker.prototype.subscribe = function(signal, scope, handlerName){
  var curryArray = Array.prototype.slice.call(arguments, 3);
  this.subscribers[signal].push(function(){
    var normalizedArgs = Array.prototype.slice.call(arguments, 0);
    scope[handlerName].apply((scope || window), curryArray.concat(normalizedArgs));
  });
}

That’s it! If you want to play with the code, just download the zipfile with the demo application and pubsub code or check out the demo - it has links to the application file, pubsub broker file, as well as the progressive build of subscribe.

23 Responses to “Decoupling Data and UI: PubSub”

  1. M. David Green Says:

    Yes, this is a summary of the key points, and I do appreciate it, but it doesn’t hold a candle to the actual presentation I sat through. Awesome! You get solid kudos for your engaging performance. It really made me want to learn more. I look forward to your next one.

  2. M. David Green Says:

    Ah, comment form fields that allow moderation, but not by the poster. My fault for having too many windows open at once. The previous comment was actually meant for another presenter, who seemed to be having a hard time on stage, but managed to make it work anyway. It should probably be deleted. But for the record, I did also enjoy your presentation, and the opportunity now to dig through the code samples at my own pace.

  3. Ajax Girl » Blog Archive » Decoupling data and UI layers with PubSub architecture Says:

    […] got a brief post along with a demo and sample code for a really compact PubSub tool, as well as a short discussion […]

  4. Garrick Cheung Says:

    I did not attend the presentation but Mariano Peterson gave me a decent recap. His enthusiastic description of your presentation stood out since we discussed it at length. I’m glad to see that you posted a summary of the presentation and a demo as well, since contemplating your concept was difficult (for not being there).

    I have been and will continue to think of how to implement your concept while my brain thinks in terms of MooTools. Good job!

  5. Javascript News » Blog Archive » Decoupling data and UI layers with PubSub architecture Says:

    […] got a brief post along with a demo and sample code for a really compact PubSub tool, as well as a short discussion […]

  6. Aniket Says:

    Hi, I had worked on a similar but a little more evolved (supports wildcard subscriptions)
    version of pubsub Details are here(http://aniketn.blogspot.com/2008/12/publish-subscribe-in-javascript.html)
    Your comments will be appreciated. Unfortunately there is no demo on that page.

  7. Decoupling data and UI layers with PubSub architecture | Slightly Nervous Says:

    […] got a brief post along with a demo and sample code for a really compact PubSub tool, as well as a short discussion […]

  8. Decoupling data and UI layers with PubSub architecture « LocalLab : Foire aux Infos Says:

    […] got a brief post along with a demo and sample code for a really compact PubSub tool, as well as a short discussion […]

  9. MagicOPromotion Says:

    Well!! I want to download software pack X-Rumer 5.0 PALLADIUM free. Any link???
    I’m so need this magic program! It’s can break captchas automatically! Activate accounts via email automatically too! Absolutely great software! Help me!
    And did you hear news - price for XRumer 5.0 Palladium will grow up to $540 after 15 may 2009… And XRumer 2.9 and 3.0 - too old versions, it’s cant break modern catpchas and cant break modern anti-bot protections. But XRumer 5.0 Palladium CAN!!!!
    So help me for download this great soft for free! Thanks!

  10. CocoChanels Says:

    Who knows where to download XRumer 5.0 Palladium?
    Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!

  11. Streetmakarov Says:

    ;)

  12. PianoTrade Says:

    PianoTrade…

    Megacool Blog indeed!… if anyone else has anything it would be much appreciated. Great website Enjoy!…

  13. payday loans Says:

    The author of blog.narcvs.com has written an excellent article. You have made your point and there is not much to argue about. It is like the following universal truth that you can not argue with: Despite the amount that you find, you or anybody else don?t recall taking off/losing their plasters at the swimming baths Thanks for the info.

  14. Massey35Juanita Says:

    Do you understand that it is the best time to receive the mortgage loans, which will help you.

  15. Xrumer Unleashed Says:

    Aw, this was a really great post. In theory I’d like to write like this also - taking time and real effort to make a good article… but what can I say… I procrastinate alot and never seem to get anything done.

  16. Orlando Vesely Says:

    I’ve been looking around for articles similar to this but by no means found one that truly was helpful such as this. Glad I observed this place!

  17. Jacob Says:

    Hej Marcus!

    I wonder what license this PubSubBroker code is under?
    I’d like to extend it and post it to GitHub if I may, pretty please :)
    Thanks in advance!

    /Jacob

  18. casino gokkasten hmsr Says:

    casino gokkasten…

    casino gokkasten…

  19. casino nederland nitb Says:

    casino nederland…

    casino nederland…

  20. wow gold Says:

    he comes to pinch my ear to wake me,

    and runs away quickly when I open my eyes angrily.

  21. cheap wow gold Says:

    I often can’t help kissing him.

    When I don’t want to get up in the morning,

  22. asyn qadm Says:

    Kasyno…

    Kasyno…

  23. carbuncle Says:

    Your blog writing is very good!Hello, I have browsed most of your posts. This post is probably where I got the most useful information for my research. Thanks for posting, maybe we can see more on this. The descriptions are literaturewow goldflavor!Good speech!