LA.NET [EN]

Sep 30

Today we’ll keep looking at the new MS AJAX library (preview 5) and we’ll start looking at the observer pattern. Wikipedia defines the observer pattern like this:

The observer pattern (a subset of the asynchronous publish/subscribe pattern) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.

In practice, implementing the observer pattern means that the observable object needs to have methods that lets eventual observers subscribe or cancel their interest in receiving notifications. The observers must also implement a predefined interface so that the subject can notify them when there’s a change in its state.

In “.NET land”, the most common implementation of this pattern relies on events: the subject exposes a public event which might be handled by one or more observers. But how does it work in JavaScript land when you’re using MS AJAX? If you’ve been using MS AJAX for some time, you’ve probably noticed that it tries really hard (too hard, if you ask me!) to mimic .NET. And that’s why you’ve got those cute OO helpers (which loose some of its initial appeal when you start “understanding” JavaScript – interesting discussion, but we’ll that to another day), events which look and feel like .NET events,etc…

Hey,did you notice that? we’ve got events which look like .NET events…that means that we can follow a similar path for implementing the pattern in MS AJAX. Lets start thinking about our subject (that is, the object that is observed). Suppose we’ve got a simple object (student) which has two properties (name and address):

var student = {
    name: "luis",
    address: "fx"
};

Now, since we want it to be observable, we need to change its API so that it uses events. But which events will we expose? nameChanged? addressChanged? Both? And what will happen if we need to add more properties in the future? If you think about it, the best option is to generate a generic event which has info about the property which was changed. Lets call it propertyChanged event! If we want to fire the event, that means that we need to change our API so that it uses the getter/setter pattern for accessing the properties. Here’s the code we need for this:

var student = {
    _events: new Sys.EventHandlerList(),
    _name: "luis",
    _address: "fx",
    get_name: function() {
        return this._name;
    },
    set_name: function(name) {
        this._name = name;
        this._raiseEvent("name");
    },
    get_address: function() {
        return this._address;
    },
    set_address: function(address) {
        this._address = address;
        this._raiseEvent("address");
    },
    add_propertyChanged: function(handler) {
        this._events.addHandler("propertyChanged", handler);
    },
    remove_propertyChanged: function(handler) {
        this._events.removeHandler("propertyChanged", handler);
    },
    _raiseEvent: function(propName) {
        var handler = this._events.getHandler("propertyChanged");
        if (handler) {
            handler(this, new Sys.PropertyChangedEventArgs(propName));
        }
    }
};

(A couple of observations before going on. The first thing to notice is that I’ve opted for using a simple object. If you’d be thinking on reusing this custom ”type”, then you’d probably be better by creating a JavaScript “class” and “putting” the methods on its prototype object. The second thing you should notice is that a better implementation of the setter would start by comparing the new value with the existing one before updating the field and raising the corresponding event.)

With the previous code, we can now add as many observers as we want. Here’s some demo code:

student.add_propertyChanged(//add an observer
    function(sender, e) {
        alert("observer 1:" + e.get_propertyName());
    });
student.set_name("john");//event will be fired

You’ll always need code which looks like this for implementing this pattern in JavaScript. Nothing prevents you from writing this code with the current release of MS AJAX. Yes, it’s doable, but it still leaves a lot of boilerplate code to the programmer. The next release of MS AJAX will cut down this work by introducing the Sys.Observer object. The idea is really simple: instead of coding everything by hand, we can just rely on that object for “adding” the necessary methods to our object. To show you how easy it is, we’ll update the previous example so that it uses the new Sys.Observer class:

var student = {
    name: "luis",
    address: "fx"
};
Sys.Observer.makeObservable(student);//"implement" observer pattern
student.add_propertyChanged(//add an observer
    function(sender, e) {
        alert("observer 1:" + e.get_propertyName());
    });
student.setValue("name”,”john");//event will be fired

Even though we didn’t add the add_porpertyChanged and setValue methods explicitly, the truth is that our student object does expose them! Those method were added by the “static” makeObservable method. Besides that method, it will also add others:

observer

As you know, JavaScript is a language where objects are dynamic and that’s why they’re easily expandable (you can simply add new properties to an object or to its prototype). The Sys.Observer object uses this feature to add the necessary methods at runtime, transforming any object into an observed object.

We won’t be talking about all the “observer methods” in this post (for instance, we’ll leave the beginUpdate/endUpdate method for a future post), but we can’t end the post without talking about setValue method. If you look at our first attempt of implementing the pattern, you’ll see that we’ve ended up adding a set_XXX method to our object because that was the only way we could intercept a property change.

When you’re thinking in a generic implementation of the pattern, you can’t really go on and dynamically add getters/setters to all the properties of the object. In this case, the best option is to add a single generic method and force every property change to go through it. And that’s why we’ve got a setValue method.

There are some downsides with using the Sys.Observer object. I guess that the worst is that you end up specifying the property name as a string when you need to update its value (and we all know how many times we get names wrong, right?). Anyway, I think that this is not enough for stopping you from using this feature.

Before ending, there’s still time for one additional note. Even though I’ve used a literal object in the samples I’ve shown, the current implementation of the “observer methods” (ie, the methods which are added to your object when you call the makeObservable method) also supports the getter/setter paradigm used by most OO classes implemented over the MS AJAX lib (in other words, before accessing the XXX property, it will try to access the set_XXX setter).

And that’s it for now. Stay tuned for more on JavaScript and MS AJAX.

6 comments so far

  1. william apken
    11:29 am - 9-30-2009

    Thanks. Keep up the good work. There is so little on the net about ajax 4 preview 5. I have switched all my current projects to asp.net ajax. The features in preview 5 will allow us to create a true posback-less site.

    With the lack of examples on the net and documentation has forced us to really examine the code. Very time consuming but as a result. My understanding of JS has greatly increased.

    Also. I think they should drop the ASP.Net from the name. I know there is support for the update panel and maybe some other things (not interested) but I think the group that is anti microsoft and asp.net may never even look at ajax 4.0. And I feel that is a shame.

    Again,
    Thanks
    William Apken

  2. Bertrand Le Roy
    7:48 pm - 9-30-2009

    Hey Luis, a quick note on a minor nitpick: given that in JS, foo[“bar”] and foo.bar are exactly the same thing, the “bar” in foo.bar actually is as much of a magic string as in the other case or as in setValue… :)
    The only difference is that we have good tooling (such as VS 2010) that enables us to reduce the likelihood of screwing up by providing us with hints of what”s already on the object. Cheers!

  3. luisabreu
    7:56 pm - 9-30-2009

    Yep, you”re absolutely right Bertrand. tools have improved so much in the last years that sometimes we forget about such details :)

  4. Sevearien
    5:01 am - 10-11-2009

    Perfect work!,

  5. Glaveth
    9:39 am - 10-12-2009

    Perfect work!,

  6. Popularlittle
    12:37 pm - 12-20-2009

    Volume No,scientist rain type reveal out child other map bird business married percent shall problem theory tradition produce player representative unit machine upper remain condition technique economy objective no day forest protection version tell we wine walk west our finance married bedroom ought rain apparent including after prison launch music close fall aim yourself without income murder event couple food transport pool tomorrow too technology someone young channel independent prevent leading understanding particular crime declare author find available area parliament inform wear now key

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>