ExtJS Cache Class (2)
February 9th, 2010 by Lloyd, under Caching, ExtJS, JavaScript, Web Development.
I had some spare time this evening so I started to play around and wrote my own client side JavaScript object cache for use with ExtJS. It’s fairly simple to use with get/set functions to call and works in terms of seconds, for example to cache a simple JavaScript object you can do:
Ext.ux.Cache.set("myJsonData",{test: 1234},10);
This would cache it for ten seconds before having it removed. I’ve even implemented some events. To be notified when items expire for example:
Ext.ux.Cache.on("expired",function(cache,removed) {
alert(removed.length + " items expired.");
});
This comes into its own with the likes of AJAX requests, one test scenario:
function dataSuccess(data) {
...
};
if (Ext.ux.Cache.has("data")) {
// Process cached data
dataSuccess(Ext.ux.Cache.get("data"));
} else {
// Request new data
Ext.Ajax.request({
url: "whatever.ashx",
scope: this,
success: function(response,options) {
// Decode data
var data = Ext.decode(response.responseText);
// Cache data for 30 seconds
Ext.ux.Cache.set("data",data,30);
// Process data
dataSuccess(data);
}
});
}
Anyhow enough of the examples here’s the actual code for you to play with:
Ext.ux.CacheEngine = Ext.extend(Ext.util.Observable,{
cache: [],
constructor: function(config) {
this.addEvents({
"added": true,
"updated": true,
"removed": true,
"expired": true
});
Ext.apply(this,config);
var cache_task = {
run: function() {
// Get current time
var now = new Date().getTime();
// Process cache items to remove
var to_remove = [];
for(var i = 0, len = this.cache.length; i < len; i++) {
// Get cached item
var item = this.cache[i];
// Check time
if (item.expires < now) to_remove.push(item);
}
// Remove items
var removed = [];
for(var i = 0, len = to_remove.length; i < len; i++) {
var item = to_remove[i];
var removed_item = {
key: item.key,
value: item.value
};
removed.push(removed_item);
this.cache.remove(item);
}
// Fire event
if (removed.length > 0) this.fireEvent("expired",this,removed);
},
interval: 1000,
scope: this
};
Ext.TaskMgr.start(cache_task);
// Call our superclass constructor to complete construction process.
Ext.ux.CacheEngine.superclass.constructor.call(config)
},
clear: function()
{
this.cache = [];
},
get: function(key)
{
// Get item
for(var i = 0, len = this.cache.length; i < len; i++) {
var item = this.cache[i];
if (key == item.key) return item.value;
}
// Return
return null;
},
set: function(key,value,timeout)
{
timeout = timeout || 10;
// Find item
for(var i = 0, len = this.cache.length; i < len; i++) {
var item = this.cache[i];
if (key == item.key) {
// Update item
item.value = value;
item.expires = new Date().getTime() + (timeout * 1000);
// Fire event
this.fireEvent("updated",this);
// Return
return;
}
}
// Add new item
var item = {
key: key,
value: value,
expires: new Date().getTime() + (timeout * 1000)
};
this.cache.push(item);
// Fire event
this.fireEvent("added",this);
},
remove: function(key)
{
// Find item
for(var i = 0, len = this.cache.length; i < len; i++) {
var item = this.cache[i];
if (key == item.key) {
// Remove item
this.cache.remove(item);
// Fire event
this.fireEvent("removed",this);
// Return
return true;
}
}
// Return
return false;
},
has: function(key)
{
// Look for key
for(var i = 0, len = this.cache.length; i < len; i++) {
// Get item
var item = this.cache[i];
// Compare keys
if (key == item.key) return true;
}
// Return
return false;
}
});
Ext.ux.Cache = new Ext.ux.CacheEngine();
I’m going to attempt to create a cached DataProxy and DataReader at some point, that should provide a more useful feature for ExtJS users so they can plug it in directly into existing code.
Ed Spencer on February 9th, 2010
Nice idea
You might be better off always assuming an asynchronous interface - synchronous can always be made to look asynchronous but the opposite is not true. Something like:
Ext.ux.Cache.get(’someKey’, function(value) {
//this gets called immediately if the cache is still fresh, or after Ajax.request if not
}, {url: ‘url/to/fetch/from’, method: ‘get’);
The third arg is optional and is passed to Ext.Ajax.request