当我向下滚动页面时,事件会多次触发

时间:2016-01-06 10:42:55

标签: javascript jquery

当用户向下滚动页面时,我尝试显示一些数据,但调用的ajax至少完成2次,有时4次。反正只有一次执行ajax调用吗?感谢。

   $(window).scroll(function () {
        if ($(document).height() <= $(window).scrollTop() + $(window).height()) {
                $.ajax({
                type : "POST",
                url : $('#AjaxMoreStatus').attr("data-url"),
                dataType : "HTML",
                beforeSend: function() {
                    $('.spinner').show();
                },
                complete: function() {
                    $('.spinner').hide();
                },
                success : function (data) {
                    $('#AjaxMoreStatus').append(data);
                }
            });
        }
    });

2 个答案:

答案 0 :(得分:4)

当您使用.scroll()事件并且滚动window时,会多次触发它。这是预期的行为。最好的方法是使用计时器,类似于500ms并等待浏览器停止滚动:

var tmr = 0;
$(window).scroll(function () {
  clearTimeout(tmr);
  $('.spinner').show();
  tmr = setTimeout(function () {
    if ($(document).height() <= $(window).scrollTop() + $(window).height()) {
      $.ajax({
        type : "POST",
        url : $('#AjaxMoreStatus').attr("data-url"),
        dataType : "HTML",
        beforeSend: function() {
          $('.spinner').show();
        },
        complete: function() {
          $('.spinner').hide();
        },
        success : function (data) {
          $('#AjaxMoreStatus').append(data);
        }
      });
    }
  }, 500);
});

这也可以将AJAX轮询保存到服务器太多次。您也可以将beforeSend()的内容带到AJAX调用和计时器的顶部。

答案 1 :(得分:0)

这是一个已知问题,它通过一种名为debouncing logic的技术解决。

  

什么是Debouncing逻辑:哪个返回一个函数,只要它继续被调用,就不会被触发。    该函数将在停止为N调用后调用   毫秒。如果立即,则触发前沿的函数,而不是尾随。

辩解逻辑:

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
  var timeout;
  return function() {
     var context = this, args = arguments;
     var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
     };
     var callNow = immediate && !timeout;
     clearTimeout(timeout);
     timeout = setTimeout(later, wait);
     if (callNow) func.apply(context, args);
  };
};

//target code/callback to be called on scroll/resize event
function callback() {
    clearTimeout(tmr);
   $('.spinner').show();
   tmr = setTimeout(function () {
     if ($(document).height() <= $(window).scrollTop() + $(window).height())  {
      $.ajax({
        type : "POST",
        url : $('#AjaxMoreStatus').attr("data-url"),
        dataType : "HTML",
        beforeSend: function() {
          $('.spinner').show();
        },
        complete: function() {
          $('.spinner').hide();
        },
        success : function (data) {
          $('#AjaxMoreStatus').append(data);
        }
    });
  }
}

//registering callback function to debouncing logic
$(window).scroll(function () {
     debounce(callback, 250);
}

现在使用debouncing逻辑,您不仅可以解决当前的问题,还可以停止担心用户何时停止滚动页面以便您可以调用目标函数,因为它可能会继续500毫秒或甚至到1

上面的代码是通用的,因此您不必对脚本上的用户交互做任何假设。

价:https://davidwalsh.name/javascript-debounce-function