Created
February 14, 2012 21:53
-
-
Save ryankshaw/1830827 to your computer and use it in GitHub Desktop.
getCache module
This file contains 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
# requires jquery | |
define 'compiled/util/getCache', -> | |
window = this | |
supports = | |
localStorage: 'localStorage' of window | |
sessionStorage: 'sessionStorage' of window | |
memCache = {} | |
# like Rails.cache.fetch. will fetch from an in-memory hash, then fall back to | |
# sessionStorage (if supported), then to an ajax request to the server. | |
# | |
# Arguments: | |
# url (string): | |
# the url that will be used for the AJAX fallback, will also be used as the cache | |
# key for memory and local storage caches, thus it needs to have its own 'cache key' | |
# that will change when the caches should be considered stale | |
# | |
# Returns: | |
# a jQuery deferred promise that will be resolved with the data you were looking for | |
# NOTE that it does not return the data itself, you must use it in an async promise-style way. | |
# Usage: | |
# currentUsersCacheKey = 'kj234whatever'; | |
# getCache('api/v1/courses.json?'+currentUsersCacheKey).then(function(currentUsersCoursesArray){ | |
# //do stuff with courses array | |
# }) | |
store = (url, cacheKey, data, storage) -> | |
if supports[storage] | |
try | |
window[storage].setItem url, JSON.stringify({data, cacheKey}) | |
catch e | |
if e.name is 'QUOTA_EXCEEDED_ERR' | |
for key, val in storage | |
try | |
if JSON.stringify(val).cacheKey | |
storage.removeItem(key) | |
break | |
catch jsonError | |
# something went wrong with JSON stringification, don't care | |
store arguments... | |
(url, cacheKey, options) -> | |
storage = if options?.storage is 'local' then 'localStorage' else 'sessionStorage' | |
existingPromise = memCache[url + cacheKey] | |
myDfd = memCache[url + cacheKey] = new $.Deferred() | |
# if we already have a promise cached in memory for this, resolve with a copy of that data | |
if existingPromise | |
existingPromise.done (cachedVal) -> | |
typeToClone = { array: [], object: {} }[$.type(cachedVal)] | |
cachedVal = $.extend true, typeToClone, cachedVal if typeToClone | |
myDfd.resolve cachedVal | |
# else if it is in DOM storage and the cacheKey it is stored with matches, resolve with that | |
else if supports[storage] and (dataWithKey = JSON.parse(window[storage].getItem(url))) and (dataWithKey.cacheKey is cacheKey) | |
setTimeout -> myDfd.resolve dataWithKey.data | |
# else get it via AJAX, cache it in localStorage and memory, then resolve with ajax's returned json | |
else | |
$.getJSON url, {cache_key: cacheKey}, (data) -> | |
store url, cacheKey, data, storage | |
myDfd.resolve data | |
myDfd.promise() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment