PDA

View Full Version : cache dataStore?



pex
24 Apr 2007, 11:22 AM
Hello,

I have a bit of a complex situation here, the problem is as follows. I have multiple comboboxes on my page which all use the same DataStore. This is a remote datastore, and the combobox uses lazyRender. Everytime a user clicks on 1 of the comboboxes the dataStore gets triggered and fires a http POST request to fetch the data... however, what I want is some sort of caching where the dataStore only retrieves the records once, stores them in memory and all subsequent calls use this memory cache.

So I embarked on a singleton journey. In this singleton I store my data:


Ext.namespace('Ext.testData');
Ext.testData = function(){

return {

getCountries: function(){
if (this.s) { return this.s; }
this.s = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: 'countries.php'
}),
reader: new Ext.data.JsonReader({
root: 'data',
totalProperty: 'total'
}, [
{name: 'code', mapping:'code'},
{name: 'name', mapping:'name'}
])
});
return this.s;
}

};
}();


Next in my comboBox code I use


var combo = new Ext.form.ComboBox({
store: Ext.testData.getCountries(),
displayField:'code',
valueField:'code',
typeAhead: true,
mode: 'remote',
triggerAction: 'all',
emptyText:'Select',
selectOnFocus:true,
lazyRender:true
});


Now my idea was whenever I make a comboBox the store would only be called once, since it's stored in a singleton. THis is true, however the OBJECT is stored in memory, not the data. So the HTTP POST is still triggered everytime I click on a combobox. Is there a way to make the data from the store local once it's receieved from the server?? or is there an other way to solve this problem? Im open to any ideas!

Thanks!

pex
25 Apr 2007, 2:59 AM
reminder? Anyone any bright ideas?

Animal
25 Apr 2007, 3:20 AM
It's a scope prob:



Ext.testData = function(){
var theStore;
return {
getCountries: function(){
if (!theStore) {
theStore= new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: 'countries.php'
}),
reader: new Ext.data.JsonReader({
root: 'data',
totalProperty: 'total'
}, [
{name: 'code', mapping:'code'},
{name: 'name', mapping:'name'}
])
});
}
return theStore;
}

};
}();

pex
25 Apr 2007, 4:24 AM
Sorry if my previous explanation was not clear enough, I hope this time it is...

Well, that part seemed to work. Your way it works too however :) The 'problem' however is that everytime the store is loaded, it sends a POST to the server. What I ideally want is that this only happens once and the store results are then stored into memory. So second time the store is requested, this cached data can be returned instead of calling the HTTP proxy again.

Any ideas on how to solve this would be more than welcome!

Animal
25 Apr 2007, 4:37 AM
Try changing the combobox's mode to local after you create it.

pex
25 Apr 2007, 5:10 AM
If I change the mode to 'local' after creation then only 1 combobox works, the other one just stays empty

cchiriac
25 Apr 2007, 5:28 AM
Just an idea : could you initialize the Store with a MemoryProxy, which you had previously created with the data from a server request ?

pex
25 Apr 2007, 5:44 AM
Just an idea : could you initialize the Store with a MemoryProxy, which you had previously created with the data from a server request ?

Good idea, I was thinking along the same lines, the problem is I don't know how to store the results from the HttpProxy into a MemoryProxy so that it is still usable by the comboBox store config. But that is *exactly* what Im after

cchiriac
25 Apr 2007, 6:04 AM
I haven't found a thread doing this (should have looked more) but from the UpdateManager.update method i can see :



var cb = {
success: this.successDelegate,
failure: this.failureDelegate,
timeout: (this.timeout*1000),
argument: {"url": url, "form": null, "callback": callback, "params": params}
};
method = method || (params ? "POST" : "GET");
if(method == "GET"){
url = this.prepareUrl(url);
}
this.transaction = Ext.lib.Ajax.request(method, url, cb, params);


and the UpdateManager.processSucces method :



processSuccess : function(response){
this.transaction = null;
if(response.argument.form && response.argument.reset){
try{ // put in try/catch since some older FF releases had problems with this
response.argument.form.reset();
}catch(e){}
}
if(this.loadScripts){
this.renderer.render(this.el, response, this,
this.updateComplete.createDelegate(this, [response]));
}else{
this.renderer.render(this.el, response, this);
this.updateComplete(response);
}
},


So what i would do, would be to create a request, and in the succces callback, instangtiate a MemoryProxy with the response. Then, use this Proxy in the Combo's Store with a JSONReader. Basically split the combo creation in two : first get the data in memory, then use a memory proxy to populate a shared Store.

Hope this makes any sense. I'm curious if this the correct approach.

madrabaz
7 May 2007, 3:05 AM
//DataStore for Countries
dsCountry = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url: './models/countries.php'}),
reader: new Ext.data.JsonReader(
{root: 'results', totalProperty: 'total', id: 'code'},
[
{name: 'code', mapping: 'code'},
{name: 'name', mapping: 'name'}
]
)
});
dsCountry.load(); // preload

comboCountry = new Ext.form.ComboBox({
triggerAction: 'all',
selectOnFocus: true,
forceSelection: true,
store: dsCountry, //use preloaded DataStore
displayField:'name',
valueField:'code',
mode: 'local' // as local
});


I hope that my solution can help you

grEvenX
27 Nov 2007, 6:55 AM
Thanks for your tip madrabaz, just as easy as it seemed :D