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.