Backbone Without AJAX - Part 1
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.
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.
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.