Last active
August 29, 2015 14:19
-
-
Save hlfbt/ce4446a42642bc5bd665 to your computer and use it in GitHub Desktop.
A simple cache for javascript. Useful to have a simple interface to share variables over between pageloads.
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
function Cache () { | |
"use strict"; | |
if (this.constructor != Cache) throw new TypeError("Constructor Cache requires 'new'"); | |
/* | |
A dumb, simple cache, to make access to cross-pageload variables easy and manageable. | |
All cache times are in milliseconds. | |
*/ | |
var storage = window['localStorage']; | |
if (storage == null) throw new TypeError("No Storage object could be acquired"); | |
function getKeys () { | |
var keys = storage['cache.keys']; | |
try { return keys = JSON.parse(keys); } | |
catch (e) { return []; } | |
} | |
function addKey (key) { | |
var keys = getKeys(), i = keys.indexOf(key); | |
if (i < 0) keys.push(key); | |
return storage['cache.keys'] = JSON.stringify(keys); | |
} | |
function removeKey (key) { | |
var keys = getKeys(), i = keys.indexOf(key); | |
if (i > 0) keys.pop(i); | |
return storage['cache.keys'] = JSON.stringify(keys); | |
} | |
function pull (key) { | |
try { | |
return [true, JSON.parse(storage['cache.cache.' + key + '.value'])]; | |
} catch (e) { | |
return [false]; | |
} | |
} | |
function put (key, item) { | |
try { | |
storage['cache.cache.' + key + '.value'] = JSON.stringify(item); | |
return true; | |
} catch (e) { | |
return false; | |
} | |
} | |
this.set = function (key, obj, time) { | |
/* | |
Set a value to the given key in the cache. | |
Returns 'null' if an error occured and the error if succesfull. | |
*/ | |
if (typeof key !== 'string' || key.length < 3 || | |
typeof time !== 'number' || time < 1) | |
return null; | |
if (put(key, obj)) { | |
storage['cache.cache.' + key + '.time'] = Date.now() + time; | |
addKey(key); | |
return obj; | |
} else | |
return null; | |
}; | |
this.get = function (key) { | |
/* | |
Retrieve a value by the given key from the cache. | |
Returns the value if succesfull, or 'null' if an error occured, the key doesn't exist or the value expired. | |
*/ | |
if (typeof key !== 'string' || key.length < 3) | |
return null; | |
var item = pull(key); | |
if (item[0]) { | |
if (this.expires(key) > 0) | |
return item[1]; | |
else // Might as well delete the expired key right away | |
this.del(key); | |
} | |
return null; | |
}; | |
this.expires = function (key) { | |
/* | |
Get the remaining time in milliseconds before this key expires. | |
*/ | |
var until = this.until(key); | |
if (until) | |
return until - Date.now(); | |
else | |
return null; | |
}; | |
this.until = function (key) { | |
/* | |
Get the time in milliseconds when this key expires. | |
*/ | |
if (typeof key !== 'string' || key.length < 3) | |
return null; | |
return +storage['cache.cache.' + key + '.time']; | |
}; | |
this.del = function (key) { | |
/* | |
Deletes a key and value from the cache. | |
*/ | |
if (typeof key !== 'string' || key.length < 3) | |
return false; | |
storage.removeItem('cache.cache.' + key + '.value'); | |
storage.removeItem('cache.cache.' + key + '.time'); | |
removeKey(key); | |
return true; | |
}; | |
this.storage = function () { | |
/* | |
Return the whole current cache in the following format: | |
{ | |
'<key1>': { | |
time: <time1>, | |
value: <value1> | |
}, | |
... | |
'<keyN>': { | |
time: <timeN>, | |
value: <valueN> | |
} | |
} | |
This will include expired keys as well! | |
*/ | |
var keys = getKeys(), cache = {}, val; | |
for (var i in keys) { | |
val = pull(keys[i]); | |
cache[keys[i]] = { | |
time : this.until(keys[i]), | |
value : (val[0] ? val[1] : null) | |
}; | |
} | |
return cache; | |
}; | |
this.clear = function () { | |
/* | |
! DANGEROUS ! | |
This completely empties the whole cache. | |
! DANGEROUS ! | |
*/ | |
var keys = getKeys(); | |
for (var i in keys) | |
this.del(keys[i]); | |
return true; | |
} | |
this.cleanup = function () { | |
/* | |
Remove broken or old keys and values. | |
*/ | |
var keys = getKeys(), time = Date.now(); | |
for (var i in keys) | |
if (!(pull(keys[i])[0] && this.until(keys[i]) >= time)) { | |
this.del(keys[i]); | |
removeKey(keys[i]); | |
} | |
return true; | |
}; | |
this.keys = function () { | |
/* | |
Return all currently cached keys, this may also include expired keys. | |
*/ | |
return getKeys(); | |
}; | |
// Cleanup on creation, we don't want to leak storage after all. | |
// It is strongly suggested to keep calling Cache.cleanup() when the app is supposed to keep running for a while. | |
this.cleanup(); | |
} | |
window.Cache = Cache; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment