Make Backbone Off-line first

The Angular teams recently announced that it will be "offline first". I assume this means 1.) Angular will cache data offline giving you the ability to build offline apps. 2.) This will be out-of-the-box functionality.

While I've built Angular apps, I prefer using Backbone. Thanks to localStorage, its actually pretty easy to make frameworks like Backbone offline.

Collections

// Extension of Backbone 1.2 Collection
var OfflineCollection = Backbone.Collection.extend({

    // Fetch the default set of models for this collection, resetting the
    // collection when they arrive. If `reset: true` is passed, the response
    // data will be passed through the `reset` method instead of `set`.
    fetch: function(options) {
        options = options ? _.clone(options) : {};
        if (options.parse === void 0) options.parse = true;

        // BEGIN OFFLINE CODE : If this collection has an offline key, then load that data while we are waiting for new data
        if (localStorage && localStorage.getItem && options.offline) {
            var storedResponse = localStorage.getItem(options.offline);
            if (storedResponse) {
                this.parse(JSON.parse(storedResponse));
            }
        }
        // END OFFLINE CODE

        var success = options.success;
        var collection = this;
        options.success = function(resp) {


            // BEGIN OFFLINE CODE : If this collection has an offline key, then store that information for later
            if (localStorage && localStorage.setItem && options.offline) {
                localStorage.setItem(options.offline, JSON.stringify(resp));
            }
            // END OFFLINE CODE

            var method = options.reset ? 'reset' : 'set';
            collection[method](resp, options);
            if (success) success.call(options.context, collection, resp, options);
            collection.trigger('sync', collection, resp, options);
        };
        wrapError(this, options);
        return this.sync('read', this, options);
    }

});

Models

// Extension of Backbone 1.2 Model
var OfflineModel = Backbone.Model.extend({

    // Fetch the model from the server, merging the response with the model's
    // local attributes. Any changed attributes will trigger a "change" event.
    fetch: function(options) {
        options = options ? _.clone(options) : {};
        if (options.parse === void 0) options.parse = true;

        // BEGIN OFFLINE CODE : If this collection has an offline key, then load that data while we are waiting for new data
        if (localStorage && localStorage.getItem && options.offline) {
            var storedResponse = localStorage.getItem(options.offline);
            if (storedResponse) {
                this.parse(JSON.parse(storedResponse));
            }
        }
        // END OFFLINE CODE

        var model = this;
        var success = options.success;
        options.success = function(resp) {

            // BEGIN OFFLINE CODE : If this collection has an offline key, then store that information for later
            if (localStorage && localStorage.setItem && options.offline) {
                localStorage.setItem(options.offline, JSON.stringify(resp));
            }
            // END OFFLINE CODE

            if (!model.set(model.parse(resp, options), options)) return false;
            if (success) success.call(options.context, model, resp, options);
            model.trigger('sync', model, resp, options);
        };
        wrapError(this, options);
        return this.sync('read', this, options);
    }

});

Usage

var model = new OfflineModel();
model.fetch({offine:"myLocalStorageKeyForThisModel"});

var collection = new OfflineCollection();
collection.fetch({offline:"myLocalStorageKeyForThisCollection"});

Algorithm

On a fetch, the code will check if there is something cached in localStorage using the passed "offline" key. If there is, it will load this data immediately while at the same time going to get data from the server. In an online scenario, the model or collection loads immediately from cache and then is completely replaced when server returns new data. Each time the server returns new data, it also updates the cache. In an offline scenario, the model or collection loads the last cached data.

comments powered by Disqus

© Balanced Scale Media, LLC. All right reserved.