In my application, I turned to the reset question by adding a new method called fetchNew :
app.Collection = Backbone.Collection.extend({ // fetch list without overwriting existing objects (copied from fetch()) fetchNew: function(options) { options = options || {}; var collection = this, success = options.success; options.success = function(resp, status, xhr) { _(collection.parse(resp, xhr)).each(function(item) { // added this conditional block if (!collection.get(item.id)) { collection.add(item, {silent:true}); } }); if (!options.silent) { collection.trigger('reset', collection, options); } if (success) success(collection, resp); }; return (this.sync || Backbone.sync).call(this, 'read', this, options); } });
This is pretty much identical to the standard fetch() method, except for checking the conditional operator for the existence of the element and using add() by default rather than reset . Unlike simply skipping {add: true} in the options argument, it allows you to retrieve sets of models that may overlap with what you have already loaded - using {add: true} an error is generated if you try to add the same thing twice model.
This should solve your caching problem, assuming your collection is configured so that you can pass some page parameter to options to tell the server which parameter page to send back. You will probably want to add some kind of data structure to your collection to keep track of which pages you loaded to avoid unnecessary queries, for example:
app.BigCollection = app.Collection.extend({ initialize: function() { this.loadedPages = {}; }, loadPage: function(pageNumber) { if (!this.loadedPages[pageNumber]) { this.fetchNew({ page: pageNumber, success: function(collection) { collection.loadedPages[pageNumber] = true; } }) } } });
source share