window 滚动:避免基于滚动高度的多次 api 命中

window scroll : avoid multiple api hits based on scroll height

我正在从 api 命中 window 滚动获取数据,即当用户在页面上达到 95% 时。问题是多次 api 命中被解雇。

我假设这是由于 js 调用的异步性质和 window 每次用户向下滚动时滚动被调用多次。

我确实放了一个变量 'taskFired' 来检查并允许 api 仅当它尚未执行时才命中逻辑。但是当用户向下滚动时,我仍然得到 4-5 api 次点击而不是 1 次。我无法找出原因。

代码如下:

//检查我们是否已经命中 api 或已达到 95% 正确度的变量 now.By 默认为 false。

var taskFired = false;

//滚动事件

$(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
                }
            };

我什至尝试过设置 setTimeout,但即使这样也不起作用:

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

$.when 文档所述,

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.

您必须确保 _self.scrollApiHit 实际上是 returns 一个承诺,否则 taskFired 将立即设置回 false。你的函数 _self.scrollApiHit 似乎不是一个承诺。

你能试试这样吗:

$(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
                });
            }
        }                
    });

我在阅读更多有关时间和延迟承诺的信息后,尝试在 ajax 成功调用中重置 taskFired。

这就是我所做的并且对我有用。

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

_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 [on success set taskFired = false]
                }
            };