Home > Enterprise >  How to only consider the lastest call of an asynchronous function (JS fetch / infinite scroll)
How to only consider the lastest call of an asynchronous function (JS fetch / infinite scroll)

Time:04-17

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).

  • Related