WinJS Event Aggregators And Observable/Evented Objects

In a previous post, I showed a very brief intro to using an application level event aggregator in WinJS. At the end of that post, I hinted at an option I was looking in to for creating localized event aggregators – basically, objects that can be observed. It turns out the path I was heading down was right, and it’s super simple to implement an evented object in WinJS.

A Brief Detour: WinJS “Class”

Before I show you how to create an evented object in WinJS, you need to know how to create a “class” in WinJS. This is done by passing a constructor function and/or a list of methods as an object literal in to a WinJS.Class.define API:

// define a "class", providing a constructor function and
// object literal to contain the methods and attributes for
// the resulting class

var MyClass = WinJS.Class.define(function(){

  // this is the constructor function

}, {

  // object literal for methods and attributes on the "class"

  doSomething: function(){
  }

});


// MyClass is now a constructor function

var m = new MyClass();
m.doSomething();

There are two other methods on the WinJS.Class object, which are also useful but not important to this blog post.

Personally, I think it’s very unfortunate that they chose to use the word “class” for this. It will be misleading and cause problems for developers that come from other languages, because people will expect the result to be a class. And while JavaScript functions can be used to create new object instances, thus behaving like a class a little, they are not classes. (For more of my thoughts, read this post on class-y frameworks)

But moving on…

Making An Object Evented

Now that we know how to build a “class” in WinJS, we can very easily add an implementation of the observer pattern to the object, allowing it to trigger events that other objects can listen to.

Here’s how you do that, using WinJS.Utilities.eventMixin:

// add the WinJS event system to MyClass

MyClass = WinJS.Class.mix(MyClass, WinJS.Utilities.eventMixin);

Yes, it’s that easy. One line of code, and you’re done. This object is now capable of triggering events and having those events listened to, which gives us everything we need to either create a dedicated event aggregator or just have our objects trigger events to facilitate workflow or other event-driven features of our app.

Triggering, Handling, and Removing Event Handlers

Triggering and handling events in an eventMixin object is a little different than in the WinJS.Application, but should be familiar to anyone that has done DOM events, jQuery events or Backbone events.

To trigger an event, call the “dispatchEvent” method and pass the name of the event as the first parameter, with the event arguments as the second parameter.

// dispatch (fire / trigger) an event
var m = new MyClass();

m.dispatchEvent("foo", {
  some: "event",
  args: "go here"
});

To handle an event triggered by another object, call the “addEventListener” method and tell it what event you want to listen to, then provide a callback function that receives the event arguments.

m.addEventListener("foo", function(args){
  // handle the event, here
});

Lastly, event handlers can be removed via a call to the “removeEventListener” method.

m.removeEventHandler("foo", eventHandlerFunction);

(You may have noticed the “useCapture” parameter in the documentation for both the addEventListener and removeEventListener methods. I have no idea what this does.)

Managing Memory

One last tip with event aggregators and evented objects: You are responsible for memory management with observable / evented objects. While this may not play out the same way that C++ forces you to allocate / deallocate memory, it’s still very true. If you allow a function to be triggered by an event, and that function is a method, then the object that holds a reference to the method runs the risk of becoming a memory leak. 

Fortunately the solution to this is easy: remove your event bindings when you’re done with them.

I’ve written about this a lot in context of Backbone and in JavaScript in general. The same rules apply to WinJS as well. In fact, I’ve had this notion in the back of my mind already, that I need to create an EventBinder object for WinJS the same way I did for Backbone.Marionette, as a core part of my own application’s memory management. We’ll see if I ever get a chance to do this, but I think it is something that needs to be done.

Just remember: it’s your responsibility as a developer to understand that this is the nature of the observer pattern and references. And just because you’re running a managed / garbage collected language, doesn’t mean you can’t create memory leaks and zombies.


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Classy Inheritance, Design Patterns, Javascript, WinJS. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Chris Tavares

    the useCapture flag is there for consistency with the DOM addEventListener APIs. It isn’t actually used for anything, and can be safely ignored (not specified).

    • http://mutedsolutions.com Derick Bailey

      good to know. thanks, chris! :)

  • http://twitter.com/sebagomez sebastian gomez

    I get ‘Object doesn’t support property or method’ Mixin on
    MyClass = WinJS.Class.Mixin(MyClass, WinJS.Utilities.eventMixin); :(

  • http://twitter.com/sachinpethani Sachin {Web-Farmer}

    Here is the nice example of event aggregation and how to cook custome winjs control.

    Hope, it may help someone to understand the event aggregators.

    See…
    http://blogs.ugidotnet.org/corrado/archive/2012/07/21/winjs-custom-controls.aspx

    Enjoy windows8 metro app with winjs/HTML5

    it rocks..!!

    Sachin {Web-Farmer}