Quick Left

This is a blog

GIFs, tech and stuff.

Backbone Without AJAX - Part 1

If you are like us here at QuickLeft, you have been writing a lot more single page JavaScript apps recently using frameworks like Backbone.

UPDATE: We're holding a full day Intro to Backbone.js workshop on June 16th, 2012. Details here.

Backbone is the Model-View-Controller JS framework we have used the most in which you can exchange data with your server by default using Rails style REST-ful AJAX calls. This can be seen in the default implementation of the Backbone.sync function, which maps your Backbone model persistence calls to HTTP verbs as follows:

The Backbone.sync method is by default quite short and simply calls $.ajax intelligently using the above mapping, a call to getURL on your model or collection, turning your model into JSON, and passing success and errors callbacks appropriately.

The Concept

It is trivial to overwrite Backbone.sync with your own function and there are several alternative implementations of Backbone.sync out there that can persist your models and collections to places like local storage or Couch DB. I have recently been enamored with dnode which offers a way of writing single page apps without worrying about AJAX at all. Instead dnode, and it's very similar rival now.js, allow you to expose server side functions to the browsers as so called remote procedure calls, RPCs. Remote procedure calling has been around for quite a while in places like the JVM. It allows you to invoke a procedure (or function or method) across the network as if it were local. The function params and result are marshaled across the network but the calling function never knows this, and can act as if the procedure were local.

Why do this? Consider that you write this nice clean DB API in JavaScript in Node.js on the server side. You write it on top of MongoDB and it has all these nice functions to find and persist models to Mongo. Then you write a single page app in Backbone. You want access to your nice DB API so you are forced by default to define HTTP routes for them that Backbone can use. With dnode you have an alternative option. You can expose these functions directly to your running code in the browser. It's not difficult either and the dnode documentation can walk you through exactly how to set it up.

An Example

Instead of rehashing the dnode documentation, I want to share a real world example of exposing a backend MongoDB like API securely. Security is usually implemented in Rails and other web frameworks at the controller level. Therefore exposing the models directly to dnode would open up your whole database to the browser. I handle this by creating a secure version of my db api, at the bottom of my normal db api file, that take a user as the first parameter. This user requires an accessToken parameter by convention. I then authenticate the user before allowing access to the db and return an error back to remote caller if the user fails authentication. Note that returning an error means invoking the result callback with an error as the first parameter, per dnode and node conventions.

Notice the use of a function whitelist to ensure that only certain functions can be invoked. To expose the db api as a dnode object I simply do this in my server.coffee:

Then on the Backbone side, I can simply overwrite Backbone.sync to invoke these functions. Stay tuned for a later post where I will show how this works with user authentication, passing finder criteria, and caching results.