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.