Skip to content

Instantly share code, notes, and snippets.

@Eccenux
Created April 1, 2016 13:28
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 Eccenux/7b83d9b964f6e0e7ec9a7fe2fce498ca to your computer and use it in GitHub Desktop.
Save Eccenux/7b83d9b964f6e0e7ec9a7fe2fce498ca to your computer and use it in GitHub Desktop.
Class providing caching for data objects (e.g. translations).
/**
* Class providing caching for data objects.
*
* It's assumed that the data comes from some remote service (otherwise there is no point in caching).
*
* @param {String} dataKey Globally(!) unique key to store data.
* @param {Storage} storageService Storage service that should have two functions:
* storageService.set(key, value) -- set data
* storageService.get(key) -- get data
* Will attempt fallback to `$.jStorage` if not secified.
* @class DataCache
*/
function DataCache(dataKey, storageService) {
// init storage service
if (typeof (storageService) !== "object") {
storageService = $.jStorage;
}
this.storage = storageService;
/**
* Load limit in seconds.
*
* After that many seconds we will attempt to refresh data (to be available next time).
*/
this.loadLimit = 10 * 60;
/**
* Forced translations reload limit in seconds.
*
* After that many seconds we will wait for new data even if we have them saved in storage.
*
* Set to `0` to ignore this limit
*/
this.forcedReloadLimit = 30 * 24 * 60 * 60;
/**
* Storage key for data.
* @private
*/
this.dataStorageKey = 'DataCache.data.' + dataKey;
/**
* Storage key for time.
* @private
*/
this.timeStorageKey = 'DataCache.time.' + dataKey;
/**
* Data state information.
*/
this.dataState = {
available: false,
needRefresh: true,
needReload: true
};
/**
* The data.
*/
this.data;
}
/**
* Initial check to be done before loading anything.
*
* @returns {Boolean} true if data is available (it's considered unavailable after `forcedReloadLimit` has passed).
*/
DataCache.prototype.check = function() {
this.dataState = {
available: false,
needRefresh: true,
needReload: true
};
if (this.storage.get(this.timeStorageKey) === null) {
return false;
}
var lastLoadTime = this.storage.get(this.timeStorageKey);
var timeDiffSeconds = Math.abs((new Date()).getTime() - lastLoadTime) / 1000;
// can preapre saved data if not too old
if (!this.forcedReloadLimit || timeDiffSeconds < this.forcedReloadLimit) {
this.data = this.storage.get(this.dataStorageKey);
this.dataState.available = true;
this.dataState.needReload = false;
}
// should skip loading
if (timeDiffSeconds < this.loadLimit) {
this.dataState.needRefresh = false;
}
return this.dataState.available;
};
/**
* Initial check to be done before loading cache.
*/
DataCache.prototype.save = function(data) {
this.storage.set(this.dataStorageKey, data);
this.storage.set(this.timeStorageKey, (new Date()).getTime());
};
function onData(data) {
// do whatever with data
}
var cache = new DataCache('MyApp.CachedThings');
if (cache.check()) {
// immediately recieve data
onData(cache.data);
// no need to refresh (for next time) - skip the rest
if (!cache.dataState.needRefresh) {
return;
// will load data, but will not wait for it
} else {
onData = function(){};
}
}
SomeAjaxLib.request({
url: 'example.com/somethind',
success: function(response) {
cache.save(response.responseText);
onData(response.responseText);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment