Skip to content

Instantly share code, notes, and snippets.

@ryankshaw
Created February 14, 2012 21:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryankshaw/1830827 to your computer and use it in GitHub Desktop.
Save ryankshaw/1830827 to your computer and use it in GitHub Desktop.
getCache module
# 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