如何停止监听事件,直到ajax请求完成

How to stop listening on event until ajax request is done

本文关键字:ajax 请求 直到 何停止 监听 事件      更新时间:2023-09-26

我正在创建一个'滚动到底部'的新闻提要,当用户滚动到页面底部时填充新闻。

我有以下代码(通过检查用户是否滚动到底部):

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       //Ajax Request
   }
});

如何确保在ajax请求填充新闻之前,用户不会向上滚动,然后再次向下滚动。换句话说,有什么干净的方法可以暂停它,直到ajax请求完成并填充了它的结果

像这样:

var request_pending = false;
function at_bottom_of_page() {
    return $(window).scrollTop() + $(window).height() > $(document).height() - 100;
}
$(window).scroll(function() {
    if (request_pending) {
        return;
    }               
    if (at_bottom_of_page()) {
        request_pending = true;
        doAjax(function (moar_news) {
            render_news(moar_news);
            request_pending = false;
        });
    }
});

在发出AJAX请求之前,取消绑定scroll处理程序。处理完AJAX响应后,重新绑定scroll处理程序。您需要给scroll处理程序一个名称,以启用解除绑定和重新绑定:

$(window).scroll(function scrollHandler() {
    if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
        $(window).off("scroll", scrollHandler);
        $.ajax({
            ...
            complete: function() {
                $(window).scroll(scrollHandler);
            }
        });
    }
});

不是这样的答案,而是一个不适合在评论中使用的注释。

对于IE6/IE7/IE8, .scroll表现不佳,每次滚动都会调用几十次(如果不是数百次)回调。在我们的项目中,我们使用一个名为.detachedScroll的包装器函数来防止这种行为:

/**
* Detached scroll prevents freezing in IE<=8
*/
if($.browser.msie && parseInt($.browser.version, 10) <= 8) {
    $.fn.scrollDetached = function(callback) {
        return $(this).each(function() {
            var oThis = this;
            clearInterval(this.detachedScrollInterval);
            this.detachedScrollInterval = setInterval(function() {
                if (oThis.hasScrolled) {
                    oThis.hasScrolled = false;
                    // Calling detached scrolling callback
                    callback();
                }
            }, 500);
            $(this).scroll(function() {
                // There was a scrolling event
                oThis.hasScrolled = true;
            });
        });
    };
} else {
    $.fn.scrollDetached = $.fn.scroll;
}

仅使用一个变量来标记是否存在未完成的ajax请求。如果是这样,不要再提出要求。否则获取数据。我的想法是,让用户滚动,为什么要阻止UI。在这种情况下,它就像进行同步调用。

var isLoading = false;
//event handler
$(window).scroll(function () {
   // check height..
   // make an ajax request if isLoading is false
   if (!isLoading) {
       $.ajax(/* .. */, success: function () {
           isLoading = false;
       }, 
       error: function () {
           isLoading = false;
       });
       isLoading = true;
   }
}

如果您仍然希望在ajax响应之前停止侦听事件,只需在ajax响应处理程序中删除绑定并重新附加它。

var isLoading = false;
addScrollEvent();
function scrollHandler(e) {
   // check height..
   // make an ajax request if isLoading is false
   if (!isLoading) {
       $.ajax(/* .. */, success: function () {
           isLoading = false;
           addScrollEvent();
       }, 
       error: function () {
           isLoading = false;
           addScrollEvent();
       });
       $(window).off('scroll', scrollHandler);
   }
}
function addScrollEvent() {
    $(window).on('scroll', scrollHandler);
}

您可以使用.off()来删除事件处理程序。

var attachEvent = function(){
    $(window).scroll(function() {
        $(window).off("scroll");
        $.ajax("example.php").done(function() { 
            //If you want to reattach event
            attachEvent(); 
        });            
    });
};
attachEvent();