Why listenTo in Backbone 0.9.9

One of Backbone’s great advantages is that it changes very little. Up until the release of 0.9.9, the Events mixin used throughout the library provided the bare minimum of functions for listening to and triggering changes in application state: dispatch to trigger an event, on to listen for it, and off to stop listening.

on and off are enough to handle events. If a view representing a collection of items wanted to update whenever the collection changed, it could listen to the corresponding events using on:

// in collection view
initialize: function () {
  this.collection.on('add', this.addItem, this);
  this.collection.on('remove', this.removeItem, this);
  this.collection.on('change', this.updateItem, this);
}

It would also be a good idea to use off to clean up when the view is closed. But in doing so, a problem emerges. Since the events are being managed by the collection, the view has no direct channel for cleaning them up. Each event must either be unbound individually:

close: function () {
  this.collection.off('add', this.addItem);
  this.collection.off('remove', this.removeItem);
  this.collection.off('change', this.updateItem);
}

Or, if all use the same context, with a slightly obscure cleanup-by-context call:

close: function () {
  this.collection.off(null, null, this);
}

Not terrible, but an easy fix can make it a whole lot better.

listenTo and stopListening provide the same functionality as on and off, but with a trick. Instead of defining events in terms of the object that triggers them, listenTo inverts management of the handlers to the listening object. Since the listener now knows exactly which handlers pertain to it, cleanup becomes much more straightforward.

initialize: function () {
  this.listenTo(this.collection, 'add', this.addItem);
  this.listenTo(this.collection, 'remove', this.removeItem);
  this.listenTo(this.collection, 'change', this.updateItem);
}

close: function () {
  this.stopListening();
}

For practical purposes, though, this will rarely happen in a view: in its infinite wisdom, Backbone 0.9.9 includes a call to stopListening() in the default view remove() method.

Let’s keep in touch

Get noise-free updates on software, product, and process.

Hey, I'm RJ: digital entomologist and intermittent micropoet, writing from the beautiful Rose City.