Backbone.js, now real time with Pusher

backbone-pusher.png

This tutorial demonstrates how to add realtime to your Backbone.js in less than 30 minutes with Pusher! It should provide you with the basis for creating rich applications with Backbone.js.

Introduction

Recently there have been a number of frameworks developed that allow you to add extra structure to your code when building rich javascript-heavy applications. These frameworks often achieve this structure by adding in layers of Models, Controllers, Views, and Events, most of the time performing synchronisation between the client and server using AJAX. One such framework that has recently grown in popularity is Backbone.js.

Update: The code associated with this post has been updated to use Backbone.js 0.5.3 and Underscore.js 1.2.1

Backbone.js

Backbone.js is a framework from DocumentCloud, which is known for it’s excellent documentation. It provides you with all the essential components required for adding structure to your rich javascript-heavy applications, including a lightweight client to server synchronisation method which requires either jQuery or Zepto.js’s AJAX functionality. Whilst this approach works the emphasis is very much on the client to manage state synchronisation, but what happens if something changes on the server? For example, if you’re building an application where two users can change the same thing at the same time?

Normally when using Backbone.js, you would have to implement your own timer and polling mechanism to check for changes on the server. This can lead to unnecessary load on the web server, and points in time between polling intervals where client and server state, and any other connected client states, are not synchronised. In the Backbone.js documentation, they use the fetch method and synchronise state like the following:

1// Poll every 10 seconds to keep the channel model up-to-date.
2setInterval(function() {
3  channel.fetch();
4}, 10000);

A better approach would be to have the server instantly notify any clients that a change has occurred. Here’s where Pusher and its real-time messaging capabilities comes in really handy because it makes it easy for any changes on the server Models to be instantly pushed to the web browser.

Making Backbone.js realtime with Pusher

To demonstrate this I’ve created a simple rails application based on the Backbone.js todo list tutorial. In doing so I’ve created a small library to connect Pusher to any Backbone.js application and called it BackPusher. Throughout this demo, we’re going to be working with two different Models, one for our todo lists, and one for our todo list items.

One special attribute to note on the todo list Model is that of a unique token, this increases security (via use of obscurity). If we were to simply use an auto incrementing integer as our list identifier, then nothing could really stop anybody guessing access how the todo lists are identified, hence allowing them to access another persons todo list. However, alternatively, rather than using public channels, we could make use of Pusher’s private channels which require the server to authenticate the request to join that channel. However, for simplicity, we won’t be going into the usage of private channels in this demo.

The library, in conjunction with some server code, synchronises the state of collections on the server with collections within the web application using Pusher as a realtime messaging component. As with all applications that use Pusher, communication between the server and all connected clients is performed using channels and events. Channels are used to uniquely represent instances models within the application and in this demo a single channel represents a todo list. In this demo, our channel names are made up of a prefix of the model name, which is “list”, followed by the todo list’s unique token, so we get:

1channel_name = "list-#{self.token}"

Events on that channel represent changes to the state of that model, so when the model changes on the server, a Pusher event is triggered. I took the approach of using a standardised naming schema for these events, using the past-tense of the standard rails CRUD verbs in which data could be changed, resulting in: created, updated, and destroyed. The following example shows how a new todo list item is created on the server, and how it is then pushed out to any connected clients via Pusher. As we’re using Rails, we’ll be using the rubygem that implements the Pusher REST API, you can find implementations for other languages over at the libraries page on our documentation.

ruby – items_controller.rb

1class ItemsController < ApplicationController
2  def create
3    list = List.find_by_token(params[:token])
4    item = list.items.create!({
5      :shortdesc =&> params[:shortdesc],
6      :isdone =&> params[:isdone]
7    })
8
9    Pusher[“list-#{list.token}”].trigger(
10      'created',
11      item.attributes,
12      request.headers["X-Pusher-Socket-ID"]
13    )
14
15    render :json =&> item
16  end
17  # …
18end

To see how all the events are hooked up on the server see the ItemsController code on github.

On the client-side we create a new Backbone collection for our list items, connect Pusher to our application using our application’s APP_KEY, subscribe to the relevant channel for the given todo list, then pass the channel and the todo list collection into BackPusher so that it can manage the synchronisation.

The code from our demo application that uses BackPusher is similar to the example below:

1app.Todos = new Backbone.Collection.extend({ … });
2
3// … bunch of other code from the tutorial ...
4
5var pusher = new Pusher(‘APP_KEY’);
6var channel = pusher.subscribe(channel_name);
7new Backpusher(channel, app.Todos);

A full code listing can be seen in application.js on github.

When an event is received on the todo list channel from Pusher the BackPusher library manipulates the todo list collection accordingly. When the collection is manipulated on the client the Backbone.sync method is called. I’ve overridden the Backbone.sync method in BackPusher code so that the AJAX request also includes the unique identifier for that client called the socket_id so that the server knows who has manipulated the collection.

For more information on the BackPusher library have a look at backpusher.js repository.

Now that both the server and the client inform each other of any form of manipulation in a todo list, we can ensure that the state on both the client and server are kept in sync in an efficient and timely fashion by using various aspects of the realtime web.

Get Pushing

Hopefully this post will provide you with the basis for creating rich applications with Backbone.js, and that BackPusher will enable you to hook them up to Pusher for real-time awesomeness.

You can grab the source code to the demo over on github. You can also get the code to just BackPusher from it’s github repository

As mentioned right at the start of this post, Backbone.js is just one framework that can benefit from integration with Pusher and we’d like to see similar adaptors for other frameworks such as SproutCore and Dojo Toolkit, and we may produce some of these ourselves if there is enough demand for them.

For more tutorials to build realtime apps, check out our