I'm not sure it is called an infinite scroll, but basically, I have a table with several thousands lines which I display in a ASP.Net Core website. The table has an advance layout where the style strongly depend on the cell content. I populate content and the style of the rows via the controller and post a JSON file.
I'm able to display let's say 20 rows of the table thanks to the JS fetch api. I'm able to scroll to the adjaceent rows smothly
I also added a separate scrollbar, so I can jump to any row from the first to the last one.
The problem is that when I stop moving the scrollbar, the rows still update for a few seconds (with the some intermediate rows, but fortunately not all) until the target ones are reached. It seems that there is some delay like if I have several asynchronous call waiting to process the update function which executes one after another.
Is there a way to only considered the latest call to the update function?
$('#fields-scroll').on('input change', async function () {
var row = $('#fields-scroll').val();
await scroll(row);
});
async function scroll(row) {
// Posts the metrics to the controller.
const response = await fetch(`${window.location.href}Fields/Interact/`, {
method: 'POST',
body: JSON.stringify({ Row: row}),
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
});
// Gets the results from the controller.
const results = await response.json();
// Makes sure that there are actual results.
if (results == null) {
return;
}
var fields = results.fields;
await populate(fields);
}
Thanks for any help!
CodePudding user response:
I think the easiest way ( without using external libs like redux-saga ) would be to use a simple debouncer to debounce the scroll action:
const handler = _.debounce(async function () {
console.log('SCROLLING');
try {
const row = $('#fields-scroll').val();
await scroll(row);
} catch (e) {
console.log(e);
}
}, 200);
$('#fields-scroll').on('input change', handler);
async function scroll(row) {
// Posts the metrics to the controller.
const response = await fetch(`${window.location.href}Fields/Interact/`, {
method: 'POST',
body: JSON.stringify({ Row: row }),
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
});
// Gets the results from the controller.
const results = await response.json();
// Makes sure that there are actual results.
if (results == null) {
return;
}
var fields = results.fields;
await populate(fields);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG ljU96qKRCWh quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="range" id="fields-scroll" />
If this is the desired effect, you can adjust the debounce timing according to your preferences. In any ase remember to always wrap the statements inside an async function inside a try-catch block, or you won't catch thrown errors.
CodePudding user response:
Incredible, it seems to work perfectly well!
I probably need to adjust the timing a bit to get some intermediate updates (and get an idea what is under the hood :-) ), but a least it does not keep updating for a few seconds when I stop moving the scrollbar.
PS I just changed the const
to var
, because it crashes when I refreshed the page (more precisely when I move back to the fields page).