Leveraging Deferreds in Backbone.js

An example to accompany my post on using jQuery deferreds in Backbone.js: http://quickleft.com/blog/leveraging-deferreds-in-backbonejs

HTML

<script src="http://documentcloud.github.com/underscore/underscore.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone.js"></script>
<script src="https://getfirebug.com/firebug-lite.js"></script>
<a href="http://quickleft.com/blog/leveraging-deferreds-in-backbonejs">Deferreds + Backbone = Awesome</a>
<pre>Loading...</pre>

CSS

a { font-family: arial, sans; margin-bottom: 2em; color: #000; display:inline-block; font-size: 12px; }

JavaScript

/* Using Deferreds in Backbone.js */

var Collection = Backbone.Collection.extend({
    // Using the response from https://gist.github.com/1431041
    url: 'https://gist.githubusercontent.com/wookiehangover/1431041/raw/61ea9a8d7aba1f09b2c547fdcf82f97c966bbc0e/fiddle.response.json',
    
    initialize: function() {
        // Assign the Deferred issued by fetch() as a property
        this.deferred = this.fetch();
    }
});

var View = Backbone.View.extend({
    render: function() {
        var _this = this;
        log('model.render() called');
        // this.collection is passed in on instantiation
        this.collection.deferred.done(function() {
            log('data returned and rendered');
            var data = _this.collection.toJSON();
            // Lets just output the response into the DOM
            $('pre').html( JSON.stringify( data, '', '  ' ) );
        });
    }
});

// Initialize the Collection - this will call Collection.fetch()
// in the initializer and sets its deferred object to 
// Collection.deferred()
var myCollection = new Collection();

// Initialize the View, passing it the collection instance
var myView = new View({
    collection: myCollection
});

// Call render immediately!
myView.render();

// This example demonstrates the ability to retain the state
// of an AJAX request as a property of a Backbone model or 
// collection. There's certaintly MORE THAN ONE WAY TO DO IT,
// but ignoring what comes with $.Deferred is ill advised!
//
// NB - Watch out for race conditions when linking Collections
// or Models with Views. eg, create all of your collections
// BEFORE creating your views, or always make your models / 
// collections responsible for instantiating views.
function log( msg ){
    console.log( msg + '\t-\t' + (new Date()).getTime());
}