Evented programming patterns: Round-up

This post is part of a series on event-driven programming. The complete series is:

Over the last few articles, I’ve covered a few of the evented programming patterns I use most often. It’s by no means an exhaustive account but there’s plenty of mileage in these simple techniques. Applying them can lead you to highly modular, flexible and responsive software. A quick recap of what we’ve seen so far:

  • Observable objects: use these when you want changes in one object to have side-effects elsewhere without hard-coding those side-effects into the object, or when you want to provide extension points for an object’s behaviour. Event listeners may fire any number of times.
  • Deferrable values: use these when multiple components need to wait for some work to complete or for some condition to hold before proceeding with their work. This pattern requires careful consideration of state, and each listener should fire exactly once.
  • Asynchronous methods: use these when you want to free up a method’s implementation to be non-blocking. Instead of returning a value immediately, the method takes a continuation that is invoked when the data it needs is ready.

These cover at least 90% of my async programming habbits when writing GUIs, and Faye (a non-blocking Bayeux client/server library) uses all three patterns extensively. Which brings me to my next point: though I’ve been doing all these articles with JavaScript, the patterns are not JavaScript-specific. JavaScript is a great language for this sort of work, which is one reason Node.js is so great, but really any language with first-class functions and lexical closures should be a good tool here. For example, two of the patterns I’ve talked about exist in Ruby as Observable, Eventful and EM::Deferrable. In the Python world there’s Twisted, though I’m afraid that’s all I can tell you about it. And it should go without saying that any halfway decent Lisp should be good at this sort of thing.

If you want to get started with evented Ruby you should really take a look at EventMachine and its various contributed gems. Ruby is a more complex language than JavaScript, especially with regard to function-like objects and its scoping rules, and personally I don’t find it as nice as JavaScript for event-driven work. It’s close, just not quite as good. To make up for criticising his screencast the other day I’m going to point you to Yehuda Katz on Ruby blocks and callables – both are required reading for working with functional Ruby.

To round off the series, I’m going to cover some general concerns when working with event-driven code. These apply to all the patterns I’ve covered; I left them out of the original articles partly so as not to repeat myself and partly so as not to obscure the core ideas being presented.

First, and I can’t stress this enough: you need to be very careful about state. In JavaScript you don’t have thread safety to worry about, but the fact remains that when you bundle up a section of code as a callback function, that code could potentially run at any time in the future. If there’s high latency in your async I/O, or if an event fires when you weren’t expecting it, your callback function needs to make sure that what it’s going to do still makes sense when it eventually gets called. For example, if you’re going to update a DOM element, does that element still exist? Apply a little paranoia and you’ll be fine.

Second, and I mentioned this in a previous post: make sure that you never write two callback functions that depend on each other. Relying on execution order means you’re very tightly coupling your code to the implementation of whatever event scheduler is managing your application, be it the browser runtime, the EventMachine loop, etc. Callbacks should be independent, atomic units of code that will behave sanely no matter when they execute. Remember: async code means you have no idea when a block of code will actually run, so don’t make any silly asumptions. The example I gave before was of two callbacks for the same event, one of which sets a value that the other is expected to use:

$("ul.tabs").bind("change", function(e) {
  // Set a value
  $(this).attr("selected", e.target);
});

$("ul.tabs").bind("change", function() {
  // Use the value
  $(this).attr("selected").show();
});

If you see code like this, consider refactoring into a single cohesive callback or find another way to decouple the event handlers.

Third it’s worth mentioning error handling. When you implement a callback system, your methods are going to be calling functions from other parts of your application, or even third party code. If one of the callbacks in a list throws an exception, you don’t want that to block execution of the other callbacks or of the rest of your method. Dean Edwards wrote about this last year, though his post specifically deals with using the DOM to dispatch events since it handles errors gracefully. Exactly how you deal with errors will depend on your app: you might not want to catch them, you might want to catch and log them, you might want to do some automatic recovery, but the important thing is you need to make a decision one way or another.

In JavaScript, you have several options. If you’re client-side, you can use the DOM as described in Dean’s article, you can use try/catch or you can use setTimeout()to schedule each callback asynchronously so it won’t block the others if it fails. Here’s a couple of examples of how you’d modify your dispatch loop; listeners is an array of [callback, scope] tuples.

// Catch errors and log them with Firebug
for (var i = 0, n = listeners.length; i < n; i++) {
  try {
    listeners[i][0].call(listeners[i][1]);
  } catch (e) {
    if (window.console) console.error(e);
  }
}

// Use setTimeout for async scheduling
for (var i = 0, n = listeners.length; i < n; i++)
  (function(x) {
    setTimeout(function() {
      listeners[x][0].call(listeners[x][1]);
    }, 0);
  })(i);

The setTimeout() illustrates the point about keeping your listeners independent – if events are dispatched asynchronously you’ve got even less of a guarantee about execution order. Most event systems do execute callbacks in sequence but there’s nothing to say they couldn’t execute them out of sequence or in parallel. It also shows how in some situations you’ll need an extra closure; in this example we use a closure to fix x to the value of i for that iteration, because if we didn’t do that the asynchronously dispatched function would use the value of i from the end of the loop every time it was called. Did I mention you should be careful with state?

Finally, think carefully about which pattern makes sense for implementing a feature. For example I recently used a Deferrable when I should have just used an async method; the stored callback hung around in memory after some initial check to decide whether to run it returned false, then the callback fired much later on when I wasn’t expecting it, resulting in multiple copies of UI elements being generated. Getting it right requires a little experience to get a feel for how to structure evented code – hopefully this series has helped point you in the right direction.

Evented programming patterns: Asynchronous methods

This post is part of a series on event-driven programming. The complete series is:

Building on the pattern for deferred processing that we just saw, asynchronous methods are typically used to return a value from a method that may have to do some work in the background to compose its return value. In an async method call, we use continuation-passing style where instead of calling the method, getting its return value then doing something with it, we send the method a continuation that it will call when it has the information we need.

Again, the typical use case for this is Ajax on the client-side, though its use has recently expanded to cover many other forms of I/O through frameworks like Node.js and EventMachine. The important thing about an async method is that it frees the implementation up to be non-blocking, since the caller is not expecting a value immediately. Instead the method being called is responsible for resuming the caller’s processing when ready.

If you’ve done any client-side work you’ll probably have made an Ajax call or two:

jQuery.get("/hello.html", function(response) {
  console.log(response);
});
console.log("done");

Compare this to the usual blocking form of I/O used by most server-side environments:

require "open-uri"
response = open("http://example.com/hello.html").read
puts response
puts "done"

The first example will print "done" before it prints the response, while the second example will print the response first. This is because with blocking I/O, your program halts while your machine goes off and does some I/O to get your data. No other work can be done until the response comes back over the wire. With the asynchronous approach, the I/O can be done in the background while your program continues working, and when the response comes back, the part of the program that needed it can run. For many forms of I/O, and especially for network calls, this can yield much more responsive applications: if web browsers used blocking I/O for Ajax, your UI would lock up every time the browser made a network call.

Implementing an async method is very straightforward compared to the other patterns we’ve covered, as it does not involve any state or long-term storage of callbacks. It will usually be based on existing async APIs provided by the host environment, and you’ll typically use it to provide abstractions on top of these APIs or to simplify the interface to a Deferrable. For example the Node APIs recently changed such that many methods now take a continuation rather than returning a deferred object (a ‘Promise’ in Node’s terms).

For example, you may have a set of data stored in a JSON document, which may be on the local machine or may be accessible over the web. You want a function to get that data as JavaScript objects just by specifying the path. Since we can do async I/O, the function will not return the parsed data directly but instead will take a continuation that we will call with the JSON-parsed document when ready.

// Using Node.js
var fs   = require("fs"),
    url  = require("url"),
    http = require("http");

getMyData = function(path, continuation, scope) {
  var uri = url.parse(path);
  if (uri.hostname) {
    var client  = http.createClient(uri.port, uri.hostname),
        request = client.request("GET", uri.pathname);
    
    request.addListener("response", function(response) {
      response.addListener("data", function(data) {
        continuation.call(scope, JSON.parse(data));
      });
    });
    request.close();
    
  } else {
    fs.readFile(path, function(err, data) {
      continuation.call(scope, JSON.parse(data));
    });
  }
};

This function wraps a couple of Node’s event-based I/O APIs and just gives your continuation the result of JSON.parse(). As covered in previous articles, the optional scope argument sets the binding of this within the continuation. This could be used to implement backing storage for a data object:

BlogPost = new JS.Class({
  initialize: function(path) {
    getMyData(path, function(data) {
      this.title = data.title;
      // more attributes ...
    }, this);
  }
});

You could imagine combining this with a Deferrable to provide a way for callers to wait for the BlogPost‘s data.

When should you reach for an async method? Well it’s basically a simplified version of the deferrable object; you’d use it where you need to hide some long-running background processing to return a value without blocking the rest of the program. It’s not as powerful as deferrables since you only get one callback per deferred value, but it has a simpler interface and requires less setup and explicit state, and for many async jobs it’s just fine. As with all evented code, you’ll need to keep in mind that your callback will fire at some not-entirely-predictable time in the future, and this makes it harder to reason about control flow and can lead to race conditions if you’re not careful about your application’s state. But for many applications, the gains in responsiveness are well worth extra discipline required.

Come back at the end of the week for a round-up of the techniques I’ve covered and what to watch out for when using them in production.

Evented programming patterns: Deferrable values

This post is part of a series on event-driven programming. The complete series is:

The Deferrable pattern is a specialisation of observable objects that mixes state into the event dispatch process. The goal is to encapsulate a long-running computation as an object that can have callbacks attached to it; each callback is called just once, as soon as the computation’s result is known. The classic client-side JavaScript example is Ajax web services: we need a piece of data from an API but we might have to go over the wire to get it. To hide these details, we may use a JavaScript API that returns a deferrable object. Multiple clients can call the API and get such an object, and all will be notified when the data is ready.

Let’s take an example. Suppose we have an API that exposes data about pictures on a photo-sharing website as JSON. A JavaScript object wraps the HTTP API and memoizes the responses. Again I’m using JS.Class and Ojay for my examples.

PhotoService = new JS.Class({
  initialize: function(host) {
    this._host = host;
    this._photos = {};
  },
  
  getPhoto: function(id) {
    if (this._photos[id]) return this._photos[id];
    var photo = new Photo();
    Ojay.HTTP.GET(this._host + '/photos', {id: id}, function(data) {
      photo.succeed(data);
    });
    this._photos[id] = photo;
    return photo;
  }
});

Our API returns a Photo object, but one whose content is initially not known. (Such an object is also known as a ‘future’ or a ‘promise’ in some contexts.) If we’ve already made a Photo with the required id we return it so as to avoid unnecessary network calls. Otherwise we make a new one, and begin an asynchronous network call to get its contents. It is not known how long the call will take but it is certainly enough to stop the method from returning anything useful immediately. So, the Photo we return is really a placeholder for a value we might know at some point in the future. A client using this API would behave like so:

var service = new PhotoService('http://example.com');
var photo = service.getPhoto('f80046');

photo.callback(function(photoData) {
  var username = photoData.user.username,
      photoUrl = photoData.url;
  
  // further processing...
});

What must the Photo look like? It must be able to have event listeners attached using callback() that wait for its value, and it must have a way of being populated with data using succeed() so that clients get the data they’re waiting for. It turns out that these are fairly generic operations and we can implement them as a module to mix into our Photo class.

Deferrable = {
  callback: function(block, scope) {
    if (this._deferredValue !== undefined)
      return block.call(scope, this._deferredValue);
    
    this._callbacks = this._callbacks || [];
    this._callbacks.push([block, scope]);
  },
  
  succeed: function(value) {
    this._deferredValue = value;
    if (!this._callbacks) return;
    this._callbacks.forEach(function(callback) {
      callback[0].call(callback[1], value);
    });
    this._callbacks = [];
  }
};

Photo = new JS.Class({
  include: Deferrable
});

This code bears some similarity to our observable object examples in that it’s just storing and calling callback functions, but there are some important differences. The callback() method checks to see if we already know the object’s value, and if we do then it calls the callback immediately and promptly forgets about it. Otherwise the callback is stored in a queue until the value is known. succeed() is what we use to give the object a value: the value is cached on the object and if any callbacks have been registered they are fired then removed from the object. This makes sure each piece of code waiting on the object’s value executes just once.

When should you use a deferrable object? The above example, though a little contrived, is the typical client-side use case but really you can use them in any situation where you need to wait for some background/parallel processing to finish. This could be an Ajax call, an animation, a complex calculation happening in another thread, etc. One case I’ve been using it for lately is where an object needs to make sure some condition is true before executing some code.

The particular example I have in mind is the Client class in Faye, a publish-subscribe messaging library for web clients. You’ll notice several of the methods, for example publish(), have their internals wrapped in a callback passed to the connect() method. This is saying, “Making sure the client is connected, run this code.” I’ve used the Deferrable pattern to implement this but it’s probably obfuscated a little by the rest of the logic, so I’ll make it more explicit here.

In Faye, each Client must connect to the server and get a clientId before it’s allowed to subscribe and publish messages. A client can therefore exist in one of three states:

  • UNCONNECTED. The client has no clientId and is not currently attempting to connect.
  • CONNECTING. The client is currently making a request for a clientId.
  • CONNECTED. The client has a clientId and may publish messages.

Therefore our connect() method must handle these three states. In the first state, we register a callback and initiate a request, and when the request returns we use succeed() to fire callbacks waiting for the Client to be ready. In the second state, we just register a callback since the request should already be in progress. In the third, we can execute the callback immediately since the Client is ready.

Client = new JS.Class({
  include: Deferrable,
  
  UNCONNECTED:  1,
  CONNECTING:   2,
  CONNECTED:    3,
  
  initialize: function() {
    this._state = this.UNCONNECTED;
  },
  
  connect: function(block, scope) {
    switch (this._state) {
      
      case this.UNCONNECTED:
        this.callback(block, scope);
        this._state = this.CONNECTING;
        Ajax.getClientIdSomehow(function(clientId) {
          this._clientId = clientId;
          this._state = this.CONNECTED;
          this.succeed(true);
        }, this);
        break;
      
      case this.CONNECTING:
        this.callback(block, scope);
        break;
      
      case this.CONNECTED:
        block.call(scope);
        break;
    }
  },
  
  publish: function(channel, message) {
    this.connect(function() {
      // publishing logic
    }, this);
  }
});

Most uses of deferrables fall into this three-state model: first we’re not ready, then we’re doing some background work to get a value, then we’re ready to use the value. They can be very useful as long as you’re careful to manage state correctly: make sure you don’t leave callbacks hanging around after they should have been fired and cleaned up, and make sure you do the right thing in each of the three states. In particular, be careful not to use a deferrable when what you really want are stateless multi-fire events (as in the previous article) or an asynchronous method – I’ll be covering those next.

Evented programming patterns: Observable objects

This post is part of a series on event-driven programming. The complete series is:

As I mentioned in the previous article, events are not things that only live in the DOM. An event is simply a point in time at which a change happens: the user clicks something, an animation completes, a piece of data changes. Events are everywhere in GUI programming and also crop up in various server-side applications, especially with the rise of Node.js. Making your APIs support events is a great way to build modular applications and keep your code maintainable and extensible at the same time.

Observable objects are simply objects that can publish events. Other parts of an application can listen to the object and execute additional code whenever the object changes in some way. This means the object can have additional functionality attached to its behaviour without modifying its source code. As a concrete example, I’m going to show how I’d implement Yehuda’s tabs example from yesterday’s post in an object-oriented style.

The markup and setup code in my implementation will look very similar:

<ul class="tabs">
  <li data-pane="first">First</li>
  <li data-pane="second" class="selected">
    Second
  </li>
  <li data-pane="third">Third</li>
</ul>

<div class="pane" id="first">Some content</div>
<div class="pane" id="second">Some content</div>
<div class="pane" id="third">Some content</div>

<script type="text/javascript">
  var tabs = new Tabs("ul.tabs");
  tabs.on("change", function(index) {
    tabs.getPanes().hide()
         .at(index).show();
  });
  tabs.select(0);
</script>

This probably looks superficially similar to the first implementation. The difference is that in this example, other scripts that want to interact with the tabs object have a proper API for doing so, so it’s clearer what behaviour is deliberate public API and what is implementation detail. In the previous version, not being able to tell the abstraction from the implementation (since it all looks like DOM code) could create serious maintenance problems later on. Our Tabs will look like this: (I’m using Ojay for this example. It has its own Observable module but we’ll ignore that for now.)

Tabs = new JS.Class({
  initialize: function(selector) {
    this._tabs = Ojay(selector).children();

    this._tabs.forEach(function(tab, index) {
      tab.on("click", function() { this.select(index) }, this);
    }, this);
  },

  select: function(index) {
    this._selectedIndex = index;
    this._tabs.removeClass("selected");
    this._tabs.at(index).addClass("selected");
    this.trigger("change", [index]);
  },

  getPanes: function() {
    var ids = this._tabs.map(function(tab) {
      return "#" + tab.node.getAttribute("data-pane");
    });
    return Ojay.apply(this, ids);
  }
});

It’s fine to have user interface widgets implemented as objects like this; in fact it can make them easier to reuse and glue together as long as they have a decent event API. Speaking of which, you’ll notice that Tabs is missing two methods our implementation depends on: on() and trigger(). These are the bedrock of any observable object, allowing other parts of the system to add listeners and allowing the object itself to notify listeners of changes. There are many ways to implement these depending on your needs, but a good starting point could look like this:

Observable = {
  on: function(eventType, listener, scope) {
    this._listeners = this._listeners || {};
    var list = this._listeners[eventType] = this._listeners[eventType] || [];
    list.push([listener, scope]);
  },
  
  trigger: function(eventType, args) {
    if (!this._listeners) return;
    var list = this._listeners[eventType];
    if (!list) return;
    list.forEach(function(listener) {
      listener[0].apply(listener[1], args);
    });
  }
};

Observable.on() takes three arguments: the name of the event, a listener function, and (optionally) a scope that this will be bound to when the listener is called. (The scope argument is useful in any JavaScript API method that takes a callback function, making it easier to use the method in an object-oriented context.) All that on() does is store the listener in a collection (this._listeners) indexed by event type.

Observable.trigger() is the other side of the bargain: it lets the object send notifications that events are taking place. First it looks to see whether there are any listeners for the triggered event, and if there are then it calls each of them with the args the event was triggered with. In our case our change event sends the newly selected index to all the listeners as this is a useful piece of information about the event that listeners are likely to use. Our application above uses the index to hide and show a series of content panes.

We can take these methods and add them to any class we like since they’re totally generic. In Ojay this is done like this:

Tabs.include(Observable);

So when should you use an observable object? The short answer is, any time you want a change to have consequences that aren’t directly related to the class at hand. The canonical example is logging, for example we may decide we want to run analytics when the tab selection changes but don’t want to bloat the class up with tracking code:

tabs.on("change", function(index) {
  pageTracker._trackPageview("/events/tabchange/" + index);
});

(See also the Facebook examples in yesterday’s article.) Think of trigger() as an extension point that opens the class up to accept new behaviour without having its source modified. The listeners you add to an object ought to be independent; the idea of the observable object is to provide a way of glueing together modules without tightly coupling them. One common gotcha (as illustrated by Yehuda’s demo) is adding listeners that depend on each other:

$("ul.tabs").bind("change", function() {
  $(this).attr("panes").hide();
  $(this).attr("selected").show();
});

$("ul.tabs").bind("change", function(e) {
  $(this).attr("selected", e.target);

  $(e.target)
    .addClass("selected")
    .siblings()
    .removeClass("selected");
});

These two listeners are bound to the same event, yet one reads and one writes the value of $(this).attr("selected"). This relies on the listeners being executed in a certain order, which is an anti-pattern in any asynchronous or event-driven system. Separate listeners ought not to know about each others’ existence, so if you have two listeners that depend on each other consider merging them into one atomic function to make sure they work correctly, or find another way to decouple them.

This piece also illustrates a more general approach that I take to building GUIs. I provide an API for scripting every atomic action the widget can perform, for example the Tabs#select(index) method. This allows multiple scripts and UI elements to control the widget. Then I wire up the UI elements in the DOM with very thin event listeners that call this API, for example

    this._tabs.forEach(function(tab, index) {
      tab.on("click", function() { this.select(index) }, this);
    }, this);

The widget’s methods perform the absolute core of required behaviour before firing any relevant events to allow other parts of the application perform additional actions. This takes a little discipline to stick to but it’s usually straightforward and yields modular, flexible and easily extensible code if you get it right.

Up next: waiting for responses with the Deferrable pattern.

Events: they’re not just for the DOM, you know

This post is part of a series on event-driven programming. The complete series is:

Over recent months we’ve seen the major JavaScript libraries talking up their event support. Back in October Luke Smith spoke about the YUI3 event system, and more recently Yehuda Katz gave a screencast on evented programming with jQuery. Dan Webb took him to task for over-zealous use of data-* attributes, arguing that the DOM is not the place to model your domain. I have a similar but more broad problem with the screencast, which is that I think the DOM is not the place for your application’s event model.

Yehuda’s talk runs through an example of creating a tabs widget using jQuery. The assertion throughout is: wouldn’t it be nice if you could treat the events in the UI widget – events like changing the visible pane, clicking a tab etc. – just like you treat DOM events. This is true up to a point, in that having a consistent event API is nice, but it fails by trying to overload the DOM with too much responsibility and creates a leaky abstraction in the process.

The initial proposition is: imagine if HTML natively supported tabs. What would that look like? One suggestion is:

<tabs>
  <tab pane="first">First</tab>
  <tab pane="second" selected="selected">
    Second
  </tab>
  <tab pane="third">Third</tab>
</tabs>

<pane name="first">Some content</pane>
<pane name="second">Some content</pane>
<pane name="third">Some content</pane>

<script type="text/javascript">
  $("tabs").bind("change", function() {
    $(this).attr("panes").hide();
    $(this).attr("selected").show();
  });
</script>

Now, the above elements don’t exist in HTML so instead it’s proposed that we get as close as we can in real HTML like so:

<ul class="tabs">
  <li data-pane="first">First</li>
  <li data-pane="second" class="selected">
    Second
  </li>
  <li data-pane="third">Third</li>
</ul>

<div class="pane" id="first">Some content</div>
<div class="pane" id="second">Some content</div>
<div class="pane" id="third">Some content</div>

<script type="text/javascript">
  // When tab selection changes, show all
  // the panes then hide the selected one
  $("ul.tabs").bind("change", function() {
    $(this).attr("panes").hide();
    $(this).attr("selected").show();
  });
</script>

This won’t work out of the box so some plumbing is needed to make ul elements support change events and tab-related attributes:

// Trigger 'change' when 'click' fires
$("ul.tabs").click(function() {
  $(this).trigger("change");
});

// On change, set the selected pane and
// toggle some class names
$("ul.tabs").bind("change", function(e) {
  $(this).attr("selected", e.target);
  
  $(e.target)
    .addClass("selected")
    .siblings()
    .removeClass("selected");
});

$(document).ready(function() {
  // Set the 'panes' attribute by getting the divs
  // referenced by the li 'data-pane' attributes
  $("ul.tabs").attr("panes", function() {
    return $("li", this).map(function() {
      return $("#" + $(this).attr("data-pane"));
    });
  });
  
  $("ul.tabs").trigger("change");
});

Don’t try this code out; even after correcting some of the more obvious typos from the screencast I still can’t get it to work. There are missing attributes (e.g. the selected attribute is never set), and in any case the DOM stringifies anything you set as an attribute so the expression $(this).attr("panes") just returns "[object Object]" rather than a list of DOM nodes.

But the thing I really want to focus on here is evented programming, and how in JavaScript there’s this unwritten assumption that if you need events, you need the DOM. In fact Yehuda nails it with this quote:

The nice thing about the browser code that we’re implementing is that it’s very familiar to you. You know how to do $("ul.tabs").click(), you know how to bind to change and add classes and get siblings. This is code that you’re already familiar with.

This reminds me of the classic quote, “When your hammer is C++, everything begins to look like a thumb.” Just because you know how one thing works, that doesn’t make it a good model for every programming task. Think about what an event is for a second. An event is just a point in time at which some change takes place. Yes, the DOM fires events all the time as changes are made to it by scripts and user interaction; these events are what power GUIs on the web. But not every event in your application needs to live in the DOM.

Let’s take a concrete example. Suppose part of your client-side app is a module that integrates your application with Facebook Connect. Your requirements list includes such items as:

  • When the user clicks a ‘Connect with Facebook’ link, they should login with Facebook and be redirected to the homepage.
  • When they complete a Facebook login or cancel the process, we should log these events using KISSmetrics.

The spirit of Yehuda’s talk is right in that we should translate this into real code that’s close to how we wrote the requirements (by the way, TDD is a great way to get into this habbit):

$("a.facebook-connect").click(function() {
  Facebook.loginAndRedirect("/");
  return false;
});

Facebook.on("login", function() {
  KM.record("Login with Facebook");
});

Facebook.on("cancel", function() {
  KM.record("Cancel Facebook login");
});

When we get around to implementing our Facebook module, how should we support these events? The first response of most JavaScripters seems to be, “Use the DOM.” But what if your events have nothing to do with the DOM? This module is a wrapper around what is essentially a web service that provides authentication and data APIs. If you had to pick a DOM node to fire these events, which would you pick? Would the fact that DOM events bubble and can be cancelled cause you problems? Do these concepts even make sense for the task at hand? My experience is that for most application-level events, they do not.

The way I like to think of the DOM is as an output device, and nothing more. I model my UI widgets and their events in pure JavaScript, providing API methods for everything the widget can do and all the events it supports. Internally, the widget takes care of hacking the DOM in whatever ways are needed to get the right look and feel. This has several benefits:

  • It leaves you free to vary the underlying HTML used to model the widget. For many complex UIs, there are several totally reasonable ways of representing them in HTML. Your markup will be subject to pressures from many directions: CSS, SEO concerns, accessibility, cross-browser requirements, new HTML features and so on. Treating widgets as native HTML objects necessarily exposes their implementation and makes them much harder to change.
  • Giving a widget a pure-JavaScript API makes it much easier to provide alternative UIs for it, since all you need is some tiny DOM event handlers that call the API. A great example of this is the Paginator class in Ojay. It exposes enough of its markup to let you style it, but its behaviour is hidden behind an API and its default control UI is totally decoupled from the widget’s core implementation. We could easily write new UIs for it and repurpose the default UI code to control other widgets with similar APIs. This is duck-typing at its best.
  • Modelling the events in JavaScript without using the DOM means you don’t need to worry about cancellation or bubbling, or which DOM node is responsible for firing the event. Users of the class just want to know that their Paginator object fired a scroll event; how the scroll is implemented in the DOM is of little concern.
  • Finally, the combination of a sensible scripting API and a good set of events makes it easier to design components that can be trivially plugged together without their code being tightly coupled. This is a cornerstone of Ojay‘s design, and is especially apparent in how easily its widgets integrate with the History module. This composability does not just apply to user interface elements, but to domain models and data services components like Ajax.

Part of Yehuda’s argument is that an object-oriented approach to GUIs doesn’t work, that writing code like

Tabs = new Class({
  initialize: function(node) {
    this.node = node;
  },
  select: function(tab) {
    // perform selection
    // behavior
  }
});

is bad because method calls assume synchronous rather than event-driven behaviour. This does not have to be the case, and as I outlined above objects are a great way to package up components and give them scripting APIs for easy integration. With that in mind, I’m going to spend this week on a series of articles on event-driven programming and common patterns for combining it with objects. The first will be on implementing events without any help from the DOM – see you tomorrow.

Faye: a Comet client and server for Node.js and Rack

I’m doing my traditional birthday software announcement a little early this year, mostly because I really want to get this out and partly because I’m doing a lot of little bits of work on old projects at the moment and this is the only fancy new thing I’ve got to show.

Spurred on by the sheer volume of awesome emanating from Music Hack Day over the weekend – a few Songkickers went over, I caught the demos via the live stream – I decided to revisit a project I worked on just before the London MHD about six months ago. My hack was this little web service that exposed your iTunes library over HTTP and let you broadcast what you were listening to to other browsers via Comet. The Comet part of it was handled by an early version of Faye, a Ruby server and JavaScript client I cooked up to provide client-to-client messaging.

The Ruby version still exists, and just gained support for Thin’s async response feature, making it totally non-blocking when used behind Thin. The more exciting news is that I’ve also ported the backend to Node.js, a JavaScript environment optimised for non-blocking asynchronous I/O. This makes it much better at serving highly concurrent Comet requests since it uses an event loop rather than blocking threads to respond to each request. It’s a straight port of the Ruby version, which is entirely event-driven except for the web server interface, since Rack expects a synchronous return to respond to requests.

Anyway, onto the code. The backends are trivial to set up, and both currently reside in a single process and keep all channel data in memory. This means you can’t use it behind Passenger (which spawns multiple Ruby processes to serve an app) but I’m hoping some bright spark can help with scaling it. Consider it a fun and reasonably nippy toy right now, I guess. To set up a backend:

// JavaScript
var faye = require('./faye');
var comet = new faye.NodeAdapter({mount: '/comet'});

# Ruby
require 'faye'
comet = Faye::RackAdapter.new(:mount => '/comet')

More complete usage examples are available in the Git repo. Both these backends provide an endpoint at http://0.0.0.0/comet that speaks the Bayeux protocol, and clients can use this to route messages between each other.

Setting up the client is a snap:

<script type="text/javascript" src="/comet.js"></script>
<script type="text/javascript">
  CometClient = new Faye.Client('/comet');
  CometClient.connect();
</script>

Each client (i.e. a JavaScript program running in a browser) can subscribe to named channels and publish arbitrary JavaScript objects to channels. Each message is distributed by the server to all the clients subscribed to that channel, and clients use a callback to handle messages from the channel.

// I can publish a message ...
CometClient.publish('/my/channel', {msg: 'Hello world!'});

// .. and you can pick it up
CometClient.subscribe('/my/channel', function(message) {
  alert(message.msg);
});

Using this it’s absolutely trivial to make simple client-to-client messaging apps – the repo contains the obligatory chat demo, which I’ve modelled on Twitter to illustrate different uses of subscriptions. You don’t need any server-side code for this aside from starting the Faye backend up to handle message routing. The next step would be to provide a client interface on the server side so your backend code can send data out to clients, but we’ll save that for a future release. Contributions in the form of scaling advice and server-side client suggestions would be very much appreciated, in the meantime go have a play with the code.