PDA

View Full Version : Getting double HTTP requests from data store / grid instantiation



Zaphod Beeblebrox
28 Jul 2014, 11:46 AM
Our code does the following:

instantiate data store
instantiate row selection paging
instantiate check box selection model
instantiate grid panel (using the above plus column model and paging tool bar)

If I embed a simple return; after the data store instantiation I get a well formed HTTP request for the data and due to the autoLoad parameters, the start is 0 and the limit is 50

If I embed a simple return; after the grid panel instantiation I get two well formed HTTP requests, one with a limit of 50 and the other with a limit of 9999.

It is this duplicate and nearly simultaneous request (which returns 920 rows) which appears to overwhelm the grid when it is rendered and it appears blank. If I click the refresh button in the pagination tool bar the grid populates as expected.

Every once in a while the grid will populate properly, but 95% of the time it just comes up empty.

You'll note a comment out section where I tried to perform a data store reload on grid render, this didn't help other than generating yet another (third) HTTP request.

I know I can tell the data store not to autoLoad, but then I'm left with an initial load from the grid instantiation of the full unlimited data request which breaks the grid yet again. I'd like to tell the grid to limit its request but I don't see how to do that in the grid properties.

ps - I also tried to set the 'start' and 'limit' as part of the data store base configuration, but it appears to ignore those settings.

Any help would be much appreciated!


Here's the actual code:


function tollfreesFilterClickHandler(btn, e) {
if(!win && currentSearchDefinition.status != 0) {

var selectionPaging, sm, tollfreesGrid;

var thisSearchTollfreesScopeParams = new extraBaseParams();
thisSearchTollfreesScopeParams.cf_action = 'init_filter_tollfrees';
thisSearchTollfreesScopeParams.search_id = currentSearchDefinition.id;
var thisSearchTollfreesScopeDS = new Ext.data.Store({
remoteSort: true,
autoLoad: { params: {start:0, limit:50} },
proxy: new Ext.data.HttpProxy({
url: 'callfinder.php?' + encodeURI(ajaxURL),
method: 'POST'
}),
reader: new Ext.data.JsonReader({
idProperty: 'tollfree',
root: 'rows',
totalProperty: 'resultcount',
fields: [
{name: 'tollfree'},
{name: 'campaign'},
{name: 'selected'},
{name: 'pure_tollfree'}
]
}),
baseParams: thisSearchTollfreesScopeParams
});

// Panel (eventually a grid) for the center
var selectionPaging = new Ext.ux.grid.RowSelectionPaging();
var sm = new Ext.grid.CheckboxSelectionModel({checkOnly: true});

var tollfreesGrid = new Ext.grid.GridPanel({
region: 'center',
store: thisSearchTollfreesScopeDS,
disableSelection: true,
loadMask: true,
cm: new Ext.grid.ColumnModel({
defaults: {
sortable: true
},
columns: [
sm,
{id:'tollfree',header: "Number", dataIndex: 'tollfree', width: 100},
{header: "Campaign", dataIndex: 'campaign', width: 260},
{header: "Selected", dataIndex: 'selected', width: 60,
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
if (record.data.selected=='1')
return '<img src="js/ext-3.3.0/resources/images/default/dd/drop-yes.gif" />';
else
return '<img src="images/blank.gif" />';
}
}
]
}),
sm: sm,
plugins: [selectionPaging],
columnLines: true,
width:400,
bbar: new Ext.PagingToolbar({
pageSize: 50,
store: thisSearchTollfreesScopeDS,
displayInfo: true,
displayMsg: 'Displaying Numbers {0} - {1} of {2}',
emptyMsg: "No numbers to display"
})
});

/*
tollfreesGrid.on({
render:{
scope: this,
fn: function() {
var store = tollfreesGrid.getStore();
//store.setBaseParam('search_id',currentSearchDefinition.id);
//store.load({params:{start:0, limit:50}});
store.reload();
}
}
});
*/

var win = new Ext.Window({
title: 'Select Numbers and Campaigns',
closable: true,
width: 475,
height: 400,
border: true,
modal: true,
layout: 'border',
items: [ tollfreesGrid ],
buttons: [{
text: 'Save Selections',
handler: function () {
parms = new extraBaseParams;
parms.cf_action = 'set_filter_tollfrees';
parms.search_id = currentSearchDefinition.id;
parms.count_of_tollfrees = selectionPaging.getSelections().length;
parms.filter_type_id = 6;

ctr = 0;
selected = selectionPaging.getSelections();
Ext.iterate(selected, function(key, value) {
++ctr;
parms["tollfree_" + ctr] = key.data.pure_tollfree;
});

Ext.Ajax.request({
method: 'POST',
url: 'callfinder.php?' + encodeURI(ajaxURL),
success: function (resp,opts) {
r = Ext.decode(resp.responseText);
if(r.status==1&&r.error==0) {
if(Number(r.saved)) refreshTabs();
if(ctr == 0) {
initTollfreesFilter();
} else {
tollfreesFilterLoadHandler();
}
} else {
Ext.Msg.alert("Could Not Update Number/Campaign Filters","There was a problem updating the tollfree/campaign filters");
}
win.close();
},
failure: function (resp,opts) {
Ext.Msg.alert("Could Not Update Number/Campaign Filters","There was a problem updating the tollfree/campaign filters, please contact customer service.");
win.close();
},
params: parms
});
}
},{
text: 'Cancel',
handler: function() {
win.close();
}
}]

}).show();
}
}

mitchellsimoens
30 Jul 2014, 4:05 AM
You are executing a reload in your render event listener and having autoLoad in your store so you are telling it to load twice.

Zaphod Beeblebrox
30 Jul 2014, 5:47 AM
Hi Mitchell,

Thanks for responding.

However, the code you referenced has already been commented out -- though it's pretty easy to miss because the forum's code tags don't do a great job of highlighting things like that.

If I remove the outer comment block /* */ on the grid render event listener then I get three HTTP requests. Two are full requests - start:0, limit:9999 and one is start:0 limit:50

So, I'm still stuck with the perplexing "extra" unbounded HTTP request.

I know I can create a data store and explicitly tell it not to make an HTTP request. But I don't know how to tell the request made by the grid, when it instantiates, to set limits on its request.

How can I do this?

mitchellsimoens
30 Jul 2014, 5:50 AM
Oh, I see the block comments now, was only paying attention to the line comments within the listener.

The grid doesn't have any code that will load the store nor does the paging store (unless you click on a button).

I personally use Chrome for my dev and when I log the XMLHttpRequests to the console, it allows me to expand the request to see the call stack that lead to the request. This would be very helpful for you to find out where in your code the request may be originating from.

Zaphod Beeblebrox
30 Jul 2014, 6:37 AM
That's very strange, because the grid is very clearly telling the data store to make an unbounded request. (I am using Chrome and tracing everything)

If I add a return; just after I instantiate the data store with autoLoad: { params: {start:0, limit:50} } then I get a single HTTP request as expected:



function tollfreesFilterClickHandler(btn, e) {
if(!win && currentSearchDefinition.status != 0) {


var selectionPaging, sm, tollfreesGrid;
var thisSearchTollfreesScopeParams = new extraBaseParams();
thisSearchTollfreesScopeParams.cf_action = 'init_filter_tollfrees';
thisSearchTollfreesScopeParams.search_id = currentSearchDefinition.id;


var thisSearchTollfreesScopeDS = new Ext.data.Store({
remoteSort: true,
autoLoad: { params: {start:0, limit:50} },
proxy: new Ext.data.HttpProxy({
url: 'callfinder.php?' + encodeURI(ajaxURL),
method: 'POST'
}),
reader: new Ext.data.JsonReader({
idProperty: 'tollfree',
root: 'rows',
totalProperty: 'resultcount',
fields: [
{name: 'tollfree'},
{name: 'campaign'},
{name: 'selected'},
{name: 'pure_tollfree'}
]
}),
baseParams: thisSearchTollfreesScopeParams
});
return;

======================================================

FORM DATA:
start:0
limit:50
authKey:182245--3d2795f481c004c9536548b7d92f67c5
ruser:cfonly_firststreet_4
search_id:3096
cf_action:init_filter_tollfrees

======================================================



If I move the return; to after the grid is instantiated I get two HTTP requests:




function tollfreesFilterClickHandler(btn, e) {
if(!win && currentSearchDefinition.status != 0) {


var selectionPaging, sm, tollfreesGrid;
var thisSearchTollfreesScopeParams = new extraBaseParams();
thisSearchTollfreesScopeParams.cf_action = 'init_filter_tollfrees';
thisSearchTollfreesScopeParams.search_id = currentSearchDefinition.id;


var thisSearchTollfreesScopeDS = new Ext.data.Store({
remoteSort: true,
autoLoad: { params: {start:0, limit:50} },
proxy: new Ext.data.HttpProxy({
url: 'callfinder.php?' + encodeURI(ajaxURL),
method: 'POST'
}),
reader: new Ext.data.JsonReader({
idProperty: 'tollfree',
root: 'rows',
totalProperty: 'resultcount',
fields: [
{name: 'tollfree'},
{name: 'campaign'},
{name: 'selected'},
{name: 'pure_tollfree'}
]
}),
baseParams: thisSearchTollfreesScopeParams
});




// Panel (eventually a grid) for the center
var selectionPaging = new Ext.ux.grid.RowSelectionPaging();
var sm = new Ext.grid.CheckboxSelectionModel({checkOnly: true});
var tollfreesGrid = new Ext.grid.GridPanel({
region: 'center',
store: thisSearchTollfreesScopeDS,
disableSelection: true,
loadMask: true,
cm: new Ext.grid.ColumnModel({
defaults: {
sortable: true
},
columns: [
sm,
{id:'tollfree',header: "Number", dataIndex: 'tollfree', width: 100},
{header: "Campaign", dataIndex: 'campaign', width: 260},
{header: "Selected", dataIndex: 'selected', width: 60,
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
if (record.data.selected=='1')
return '<img src="js/ext-3.3.0/resources/images/default/dd/drop-yes.gif" />';
else
return '<img src="images/blank.gif" />';
}
}
]
}),
sm: sm,
plugins: [selectionPaging],
columnLines: true,
width:400,
bbar: new Ext.PagingToolbar({
pageSize: 50,
store: thisSearchTollfreesScopeDS,
displayInfo: true,
displayMsg: 'Displaying Numbers {0} - {1} of {2}',
emptyMsg: "No numbers to display"
})
});
return;


======================================================

FORM DATA:
start:0
limit:9999
authKey:182245--3d2795f481c004c9536548b7d92f67c5
ruser:cfonly_firststreet_4
search_id:3096
cf_action:init_filter_tollfrees


FORM DATA:
start:0
limit:50
authKey:182245--3d2795f481c004c9536548b7d92f67c5
ruser:cfonly_firststreet_4
search_id:3096
cf_action:init_filter_tollfrees

======================================================

mitchellsimoens
30 Jul 2014, 6:40 AM
That's not saying anything tho, the call stack will tell you what file and line the methods are being executed on so you can firmly say, yes that class is doing it.

Zaphod Beeblebrox
30 Jul 2014, 6:44 AM
OK, please forgive my ignorance... Call Stack?

Zaphod Beeblebrox
30 Jul 2014, 7:03 AM
OK, I think I found what you mean abour the call stack, but I don't see how this changes anything in that there are still two requests, though the unbounded one is deeper than the limited one...




XHR finished loading: POST "http://192.168.11.233/reports/www/callfinder.php?authKey=182245--3d2795f481c004c9536548b7d92f67c5&ruser=cfonly_firststreet_4". ext-base.js:7

iext-base.js:7
Ext.lib.Ajax.k.requestext-base.js:7
Ext.extend.requestext-all.js:7
Ext.extend.doRequestext-all.js:7
Ext.extend.requestext-all.js:7
Ext.data.Store.Ext.extend.executeext-all.js:7
Ext.data.Store.Ext.extend.loadext-all.js:7
Ext.extend.selectDbItemsRowSelectionPaging.js:247
Ext.extend.initRowSelectionPaging.js:34
Ext.extend.initPluginext-all.js:7
Ext.Componentext-all.js:7
Kext-base.js:7
Kext-base.js:7
Kext-base.js:7
Kext-base.js:7
tollfreesFilterClickHandlerfilterClickHandler.js?20130401:211
h.Event.fireext-all.js:7
h.Observable.fireEventext-all.js:7
Ext.Button.Ext.extend.onClickext-all.js:7
Kext-all.js:7




XHR finished loading: POST "http://192.168.11.233/reports/www/callfinder.php?authKey=182245--3d2795f481c004c9536548b7d92f67c5&ruser=cfonly_firststreet_4". ext-base.js:7

iext-base.js:7
Ext.lib.Ajax.k.requestext-base.js:7
Ext.extend.requestext-all.js:7
Ext.extend.doRequestext-all.js:7
Ext.extend.requestext-all.js:7
Ext.data.Store.Ext.extend.executeext-all.js:7
Ext.data.Store.Ext.extend.loadext-all.js:7
(anonymous function)ext-base.js:7

mitchellsimoens
30 Jul 2014, 7:05 AM
The first one is coming from a button click:


Ext.Button.Ext.extend.onClick ext-all.js:7

Then it gets into whatever filterClickHandler.js is:


tollfreesFilterClickHandler filterClickHandler.js?20130401:211

Then it gets into RowSelectionPaging.js. What is Ext.ux.grid.RowSelectionPaging?

Zaphod Beeblebrox
30 Jul 2014, 7:18 AM
Came bundled with ExtJS 3.x.x

/**
* Ext.ux.grid.RowSelectionPaging plugin for Ext.grid.GridPanel
* A grid plugin that preserves row selections across paging / filtering of the store.
*
* @author Joeri Sebrechts
* @date April 14th, 2010
*
* @class Ext.ux.grid.RowSelectionPaging
* @extends Ext.util.Observable
*/

One of our developers implemented it to handle row selections across multiple pages. Thanks for the tip on this, though. I see in the ux file that there is a reference to: "large datasets could cause slow instatiation"

Ugh... It appears this problem has been waiting to strike since it was implemented and now is biting us because there are now data sets that are large enough to slow things down so it looks like the grid is empty - if I wait minutes it populates.

Now I have to figure out how to paint a mask while it loads...

mitchellsimoens
30 Jul 2014, 7:20 AM
It didn't come bundled with Ext JS 3. I see it in the forums under Ext JS 2 forums as a user extension by joeri

Zaphod Beeblebrox
30 Jul 2014, 7:28 AM
Really? Strange, it's in our ext-3.3.0 folder in a /ux/ folder.

Now that I know where to look, I have to figure out a workable solution. Thank you for pointing me in the right direction...