javascriptjqueryajaxinfinite-scrollendlessscroll

infinite scroll duplicate ajax call


I'm having hard time figuring how to avoid duplicate ajax call for my infinite scroll javascript code. It mostly works but sometimes i have 2 or 3 times the same ajax page call causing a sort of loop. How to avoid this? Thanks

//infiniteScroll
var currentPage = 1;
var intervalID = -1000;
var scroll = false;

$('document').ready(function(){
    if ( scroll == true) {
        if (window.location.pathname == "/" && window.location.search == "" && $('#items_container').length > 0) {
            $('.pagination').hide();
            intervalID = setInterval(checkScroll, 300);
        }
    };
})

function checkScroll() {
  if (nearBottomOfPage()) {
        currentPage++;
    jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get', 
        beforeSend: function(){
            var scroll = false;
            $('.spinner').show();               
        },
        success: function(data, textStatus, jqXHR) {
            $('.spinner').hide();
            $('#items_container').append(jQuery(data).find('#items_container').html());
            var scroll = true;
            if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
                clearInterval(intervalID);
        }
    },});
  }
}
}

function nearBottomOfPage() {
  return scrollDistanceFromBottom() < 450;
}

function scrollDistanceFromBottom(argument) {
  return pageHeight() - (window.pageYOffset + self.innerHeight);
}

function pageHeight() {
  return Math.max(document.body.scrollHeight, document.body.offsetHeight);
}

Solution

  • It looks like the checkScroll function is being called every 300 milliseconds, and it's possible that an AJAX request will take longer than that.

    I see you've got the scroll variable, but you are only checking the value of it on the initial document load, which won't affect the timer.

    I would suggest having a look at listening to the scroll event instead of creating a timer: jQuery docs. You could then do something like the following to prevent two ajax calls running:

    var ajaxRunning = false;
    
    function checkScroll() {
        if (!ajaxRunning && nearBottomOfPage()) {
            currentPage++;
    
            ajaxRunning = true;
    
            jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get', 
            beforeSend: function(){
                $('.spinner').show();               
            },
            success: function(data, textStatus, jqXHR) {
                $('.spinner').hide();
                $('#items_container').append(jQuery(data).find('#items_container').html());
                if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
                    clearInterval(intervalID);
            },
            complete: function() {
                ajaxRunning = false;
            }
        },});
      }
    }