Skip to content

Instantly share code, notes, and snippets.

@hlfbt
Last active August 29, 2015 14:19
Show Gist options
  • Save hlfbt/ce4446a42642bc5bd665 to your computer and use it in GitHub Desktop.
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.
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