I’m doing Angular 2 infinite scrolling for ag-grid and got an issue to synchronize data portion with setRowData. The duplication problem comes after 1st scrolling event handler is called (to get 2nd portion of the data as the 1st was loaded originally, before scrolling) and HTTP request for the page’s data portion is sent. Since only asynchronous HTTP request is now available (synchronous was deprecated), the control is passed to setRowData BEFORE HTTP Response is received. As a result, old row data’s used to populate grid, and 1st & 2nd pages look identical. Any attempts to block execution of setRowData UNTIL HTTP Response arrives, failed. setIntervals() & setTimeout() didn’t block while “while” loop blocked EVERYTHING including HTTP Request/ Response. In latter case, the execution just hangs forever as the condition for the loop exit never met since this flag is updated only after Response is processed. Neither could I make HTTP request synchronous. Bellow’s the code of HTTP function:
private getDataPortionFromServer = function(startRow: number, endRow: number, firstTime: boolean) {
console.log('getDataPortionFromServer: lastEndRow = ' + this.lastEndRow + ', current endRow' + endRow);
if (this.lastEndRow == endRow) {
console.log('getDataPortionFromServer: exiting to avopid dup call');
return;
}
var url: string = ...; //co
function getDataSynchronously(url, callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.setRequestHeader('Accept','*/*');
httpRequest.setRequestHeader('Content-Type','application/json');
sac.stillRetrieveing = true;
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
if (typeof callback == "function") {
// apply() sets the meaning of "this" in the callback
callback.apply(httpRequest);
}
}
}
httpRequest.send();
}
getDataSynchronously(
url,
function() {
console.log('Rrocessing Response : ' + '[' + new Date().toUTCString() + '] ');
var hs = this.responseText;
//doing something with data in this.responseText;
var rd = sac.fitInColumnDefinition(httpResult[0].data); // 'rd' is actual row data for a page
stillRetrieveing = false; // !!! this is the flag; if false, execution may continue
// otherwise execution should wait until stillRetrieveing = false
if (firstTime) { //1st portion of Row Data before any scrolling
setRowData(rd); //1st time no issue, problem comes when scrolling starts
}
sac.rowData = rd;
}
);
}
//Here's setRowData:
private setRowData(allOfTheData) {
var sac: SampleAppComponent;
sac = this;
var dataSource = {
rowCount: null, // behave as infinite scroll
pageSize: sac.pageSize,
overflowSize: sac.pageSize,
maxConcurrentRequests: 2,
maxPagesInCache: 2,
getRows: (params:any) => {
console.log('asking for ' + params.startRow + ' to ' + params.endRow);
sac.getDataPortionFromServer(params.startRow, params.endRow, false); // !!! asynchronous, comes immediately to
// next line: allOfTheData = sac.rowData
// without waiting for fresh row data
/*
Realy need here some blocking mechanism that would allow:
a) block execution before the next line "allOfTheData = sac.rowData;"
b) during blocking, be able to observe somehow value of 'stillRetrieveing' flag and detect when it changes
(something like volatile in JAVA)
c) never exit blocking unless stillRetrieveing == false
*/
setTimeout( function() {
allOfTheData = sac.rowData;
// take a slice of the total rows
var dataAfterSortingAndFiltering = sac.sortAndFilter(params.sortModel, params.filterModel, allOfTheData);
// if on or after the last page, work out the last row.
var lastRow = parseInt(sac.rowsReturned);
// call the success callback
params.successCallback(dataAfterSortingAndFiltering, lastRow);
}, 500);
} //getRows: function (params)
}; //var dataSource
this.gridOptions.api.setDatasource(dataSource);
}
Would be greatly appreciate any advise or clue.