Skip to content

Instantly share code, notes, and snippets.

@muthuspark
Created November 23, 2016 05:16
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 muthuspark/1715243ddb4eb56d6e0730ddebf304a5 to your computer and use it in GitHub Desktop.
Save muthuspark/1715243ddb4eb56d6e0730ddebf304a5 to your computer and use it in GitHub Desktop.
API Response Caching System
/**
* API Response Caching System
* This module creates a global variable called 'apicache' and makes it available throughout.
*/
(function() {
/**
*
* Variables to store our XMLHttpRequest object methods
*/
var open = window.XMLHttpRequest.prototype.open,
send = window.XMLHttpRequest.prototype.send,
onReadyStateChange;
/**
* The prefix helps in keeping our keys unique making sure it doesn't conflict with the other keys
*/
var _keyprefix = "_storagekey_";
/**
* The regex to replace all my UUIDs to some other more easily storable format
*/
var uuid_regex = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g;
/**
* XMLHttpRequest object
*/
var xmlhttp = window.XMLHttpRequest;
var url;
/**
* Method that overrides our XMLHttpRequest open method
*
* @param String method GET,POST,PUT,DELETE etc
* @param String url API url
* @param String async sync or async
*/
function openReplacement(method, url, async) {
var syncMode = async !== false ? 'async' : 'sync';
this.url = url;
return open.apply(this, arguments);
}
/**
* Method that overrides our XMLHttpRequest send method
*
* @param Object data object passed as payload
*
*/
function sendReplacement(data) {
//console.log('Sending HTTP request data : ', data);
if (this.onreadystatechange) {
this._onreadystatechange = this.onreadystatechange;
}
this.onreadystatechange = onReadyStateChangeReplacement;
return send.apply(this, arguments);
}
/**
* Method thats called when the response is recived from the server
*/
function onReadyStateChangeReplacement() {
//console.log('HTTP request ready state changed : ' + this.readyState);
//console.log(this.responseText);
if (this.status == 200) {
//store only if the route returns success
storeIntoCache(this.url, this.responseText);
}
if (this._onreadystatechange) {
return this._onreadystatechange.apply(this, arguments);
}
}
/**
* Store data into cache. url as key and responseText as value
*/
function storeIntoCache(url, responseText) {
if (urlRegisteredForCache(url)) {
sessionStorage.setItem(_keyprefix + url, responseText);
}
}
/**
* Get From Cache using the URL as key.
*/
function getFromCache(url) {
return JSON.parse(sessionStorage.getItem(_keyprefix + url));
}
function urlRegisteredForCache(url) {
var getroutes_tocache = JSON.parse(sessionStorage.getItem('getroutes_tocache'))
if (getroutes_tocache && getroutes_tocache.indexOf(url) > -1) {
return true;
}
return false;
}
function dataCachedInStorage(url) {
return sessionStorage.getItem(_keyprefix + url);
}
//Overriding
window.XMLHttpRequest.prototype.open = openReplacement;
window.XMLHttpRequest.prototype.send = sendReplacement;
function getstoredgetroutes() {
return JSON.parse(sessionStorage.getItem('getroutes_tocache'));
}
//We create our Cache class
function Apicache() {
}
//get data from cache
Apicache.prototype.get = function(url) {
return JSON.parse(sessionStorage.getItem(_keyprefix + url));
}
//delete data from cache
function remove(geturl) {
sessionStorage.removeItem(_keyprefix + geturl);
if (window.debug) {
console.info("data removed from cache" + geturl);
}
}
/**
* check If This Route Affects Any Cached Data
*/
Apicache.prototype.checkIfThisRouteAffectsAnyCachedData = function(url) {
url = url.replace(uuid_regex, "{{id}}");
var urlsthatwillaffectthisget_tocache = JSON.parse(sessionStorage.getItem('urlsthatwillaffectthisget'));
if (urlsthatwillaffectthisget_tocache && urlsthatwillaffectthisget_tocache[url]) {
urlsthatwillaffectthisget_tocache[url].forEach(function(geturl) {
remove(geturl);
});
}
}
/**
* Register the passed url for caching. Registering basically means
* I will make sure the API response for this URL is cached
*/
Apicache.prototype.register = function(geturl, urlsthatwillaffectthisget) {
var getroutes_tocache = JSON.parse(sessionStorage.getItem('getroutes_tocache'));
if (!getroutes_tocache) {
getroutes_tocache = []; //create a fresh variable
}
if (getroutes_tocache.indexOf(geturl) == -1) {
getroutes_tocache.push(geturl);
}
var urlsthatwillaffectthisget_tocache = JSON.parse(sessionStorage.getItem('urlsthatwillaffectthisget'));
if (!urlsthatwillaffectthisget_tocache) {
urlsthatwillaffectthisget_tocache = {}; //create a fresh variable
}
if (urlsthatwillaffectthisget) {
urlsthatwillaffectthisget.forEach(function(uwa) {
var uwa = uwa.replace(uuid_regex, "{{id}}");
if (!urlsthatwillaffectthisget_tocache[uwa]) {
urlsthatwillaffectthisget_tocache[uwa] = [];
}
urlsthatwillaffectthisget_tocache[uwa].push(geturl);
});
sessionStorage.setItem('urlsthatwillaffectthisget', JSON.stringify(urlsthatwillaffectthisget_tocache));
}
sessionStorage.setItem('getroutes_tocache', JSON.stringify(getroutes_tocache));
}
//A top level global instance where all the public ojects will be attached
var apicache = new Apicache();
// Attach the instance to window to make it globally available
window.apicache = apicache;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment