1

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);
}
Jonnyx Delavilla
  • 545
  • 9
  • 22
  • to add new data every time,you have to call ajax every time – ɹɐqʞɐ zoɹǝɟ Apr 11 '14 at 13:02
  • You *will* get multiple trigger events with your code, so you need to flag the load-in-progress state, e.g. via an attribute. Use the attribute to decide to call your Ajax code, so you do not repeat requests for the same page. On completion (success or fail) you clear the attribute. You might as well try one of the many free infinite scrollers out there. Some are Google compliant (by making use of existing paging links on the page). – Gone Coding Apr 11 '14 at 13:06

2 Answers2

2

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;
        }
    },});
  }
}
jackfrankland
  • 1,972
  • 1
  • 11
  • 11
2

Set async to false, or create a variable like

var isLoading = false;

In before send set it to true. On success set it false again. And before sending the ajax call, check if isLoading isn't true. If it is, return out of the function or put a loop inside with a spinner, which will be checking for the isLoading value so it fires the ajax first after isLoading was set to false.

Example:

function checkScroll() {
  if (nearBottomOfPage() && isLoading === false) {
    currentPage++;

    jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get', 
    beforeSend: function(){
        var scroll = false;
        $('.spinner').show();
        isLoading = true;               
    },
    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);
          isLoading = false;
        }
    },
  });
  }}}
jPO
  • 1,984
  • 1
  • 13
  • 24