Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching collections in backbone.js?

What would be the best way to ensure that my collection stays cached and thereby only gets fetched once?

Should I implement some sort of cache layer? Should I share the Collection variable to wherever it is needed? Can I trust jQuerys AJAX setting? ($.ajaxSetup ({ cache: true });)

The basic collection as it looks right now:

theCollection = Backbone.Collection.extend({
    model: theModel,
    url: "source.json"
});

if (typeof myCollection === 'undefined') {
    var myCollection = new theCollection; // Only allow it to be created once
}
like image 561
Industrial Avatar asked Dec 11 '11 22:12

Industrial


2 Answers

I would implement a sort of collection manager in your case:

var manager = (function(){

  var constructors = {
    'example': ExampleCollection
  };
  var collections = {};

  return {
    getCollection: function(name) {
      if(!collections[name]) {
        var collection = new constructors[name]();
        collection.fetch();
        collections[name] = collection;
      }
      return collections[name];
    }
  }
})();

Here the manager is responsible for instantiating collections and fetching them. When you call:

var exampleCollection = manager.getCollection('example');

you get an instance of example collection with data being already fetched. Whenever you need this collection again you can call the method again. You will then get the exact same instance with no need to fetch it again.

This is just a very simple manager example, and there are a lot of additional features you can implement and enhance.

I would strongly advise not to handle this issue on a lower level (eg. the transport layer of $.ajax). If you do that, you would prevent your collection from getting fetched multiple times, but you end up having different model instances with the same id floating around your application. Every collection instance would create it's own models.

In a CouchApp I am currently working on, I also found it necessary to prevent duplicate model instances in different collections (different db views can return the same model data). This has been solved by having a separate collection in the manager, which keeps track of all models already loaded into the application.

Last but not least you might consider implementing a refresh method in your collections or the manager that will handle updating the collection from the server. If you do this with the fetch method your whole collection is reseted so all models are destroyed and then recreated. This is bad if you have models from this collection referenced somewhere else in the app (as you typically do). Those instances are outdated and duplicated in your app then. The refresh method checks wether instances with the incoming id are already present in the curent collection. If so they are updated, otherwise they are added.

like image 92
ProTom Avatar answered Nov 01 '22 07:11

ProTom


If by caching you actually mean a singleton, so that you can reference the same domain list from multiple places in a modular JS application, we use RequireJS for this. You can separate your collection to be a module in the application, which you then require wherever you are using it. In pseudocode:

require(["myCollection"],
    function(myCollection) {
        var MyView = Backbone.View.extend();
        new MyView({
            collection: myCollection
        }).render();
    }
);

Your callback function will always get the same instance you returned when you define your myCollection module. Bind to that instance from all your views, and whenever it is refreshed, those views will get an event trigger and can update themselves.

like image 27
Lauri Piispanen Avatar answered Nov 01 '22 08:11

Lauri Piispanen