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);
}
2
  • to add new data every time,you have to call ajax every time Commented Apr 11, 2014 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). Commented Apr 11, 2014 at 13:06

2 Answers 2

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;
        }
    },});
  }
}
Sign up to request clarification or add additional context in comments.

Comments

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;
        }
    },
  });
  }}}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.