Created
October 25, 2012 02:31
-
-
Save tbranyen/3950130 to your computer and use it in GitHub Desktop.
Cache Backbone Model and Collection fetch calls with a deferred, simple and intuitive.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* backbone.cacheit.js v0.1.0 | |
* Copyright 2012, Tim Branyen (@tbranyen) | |
* backbone.cacheit.js may be freely distributed under the MIT license. | |
*/ | |
(function(window) { | |
"use strict"; | |
// Localize global dependency references. | |
var Backbone = window.Backbone; | |
var $ = window.$; | |
var _ = window._; | |
// Patch the fetch method to retain a reference. | |
_.each(["Model", "Collection"], function(ctor) { | |
// Retain a copy of the original fetch method, since we are overidding it. | |
var oldFetch = Backbone[ctor].prototype.fetch; | |
// Override both Model and Collection `fetch` methods. | |
var newFetch = Backbone[ctor].prototype.fetch = function(options) { | |
options = options || {}; | |
// Save a reference to the original deferred. | |
var oldDef = this._def; | |
// Return early. | |
if (this._def && !options.reload && !this.reload) { | |
return this._def.promise(); | |
} | |
// If a deferred doesn't exist, create one. If the clear flag is provided, | |
// jump in to create a new deferred. | |
this._def = newFetch.deferred(); | |
// If the clear was provided and there is an existing deferred, resolve it | |
// once this has resolved. | |
if (options.reload && oldDef) { | |
this._def.done(oldDef.resolve); | |
} | |
// Call the original `fetch` method and store its return value (jqXHR). | |
var req = oldFetch.apply(this, arguments); | |
// Once the request has finished, resolve this deferred. | |
req.done(_.bind(function() { | |
this._def.resolveWith(this, [this]); | |
}, this)); | |
// Return the deferred to wait with. | |
return this._def.promise(); | |
}; | |
// Allow the jQuery dependency to be swapped out to use this in other | |
// enviornments. | |
Backbone[ctor].prototype.fetch.deferred = function() { | |
return $.Deferred(); | |
}; | |
}); | |
})(this); |
Great solution, Tim! Thanks.
I've done a bit of work with a CachingModel mixin which attempts to address HTTP ETag caching / 304 Not-Modified responses. At some point it would be amazing to integrate with this.
Very useful! Thanks! :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Glad to see this. Many of my models only need to fetch, and they do that from a fairly static data set, so I've had to do something similar. Nice to see a concise solution we can all develop and share.