sahil sahil - 6 months ago 9
jQuery Question

window scroll : avoid multiple api hits based on scroll height

I am getting data from the api hit on window scroll i.e. when user reaches 95% down on the page. The issue is multiple api hits are getting fired.

I am assuming this is due to asynchronous nature of js calls and window scroll being called multiple times for each time user scroll down.

I did put a variable 'taskFired' to check and allow api hit logic only if its not executing already. But still when user scrolls down, i am getting 4-5 api hits instead of 1. I am unable to figure out the reason.

The code looks like:

//variable to check if we are already hitting api or have reached 95% right now.By default it is false.

var taskFired = false;


//scroll event

$(window).scroll(function (evt) {
if (!taskFired) { //allow to check and hit api if taskFired is false
$.when(_self.scrollApiHit()).then(function () {
taskFired = false; //reset variable when api hit done
});
}
});

_self.scrollApiHit = function () {
var wintop = $(window).scrollTop(), docheight = $(document).height(), winheight = $(window).height();
var scrolltrigger = 0.95;

if ((wintop / (docheight - winheight)) > scrolltrigger) {
taskFired = true;
//API HIT
}
};


I even tried putting setTimeout but even this is not working:

setTimeout(function () {
if (!taskFired) {
$.when(_self.scrollApiHit()).then(function () {
taskFired = false;
});
}
},1000);

Answer

As the $.when documentation states,

If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.

You have to make sure that _self.scrollApiHit actually returns a promise, otherwise, taskFired will be set back to false immediately. Your function _self.scrollApiHit doesn't seem to be a promise.

Could you try something like this:

$(window).scroll(function (evt) {
        if (!taskFired) {               
            var wintop = $(window).scrollTop(), docheight = $(document).height(), winheight = $(window).height();
            var scrolltrigger = 0.95;    

            if ((wintop / (docheight - winheight)) > scrolltrigger) {
                taskFired = true;
                $.when($.ajax("API HIT HERE")).then(function () {
                    taskFired = false; //reset variable when api hit done
                });
            }
        }                
    });