滚动事件触发次数过多.我只希望它每秒最多发射一次

Jon*_*Ong 60 javascript

我有一个"无限滚动"的页面.它会计算页面末尾与当前页面之间的差异,如果此差异足够小,则会加载更多内容.使用jQuery代码是这样的:

$(window).on('scroll', function() {
    if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
        # load more content via ajax
}
Run Code Online (Sandbox Code Playgroud)

现在,问题在于每次滚动时,每个滚动都会触发此事件多次.我想每隔x毫秒发射一次.我该怎么做?

nic*_*des 38

查看Underscore.js库的"油门"方法.

http://underscorejs.org/#throttle

它给出的示例正是您所要求的 - 限制您处理滚动事件的频率.

  • 查看源代码以强调(这是非常好的文档记录),然后拔出油门. (23认同)
  • 非常棒的库,但我试图避免任何依赖. (2认同)

jfr*_*d00 38

解决此问题的一种方法是定义时间间隔,并且仅在该时间间隔内处理一次滚动事件.如果在该时间间隔内有多个滚动事件进入,则忽略它并仅在该时间间隔过去时处理它.

var scrollTimer, lastScrollFireTime = 0;

$(window).on('scroll', function() {

    var minScrollTime = 100;
    var now = new Date().getTime();

    function processScroll() {
        console.log(new Date().getTime().toString());
    }

    if (!scrollTimer) {
        if (now - lastScrollFireTime > (3 * minScrollTime)) {
            processScroll();   // fire immediately on first scroll
            lastScrollFireTime = now;
        }
        scrollTimer = setTimeout(function() {
            scrollTimer = null;
            lastScrollFireTime = new Date().getTime();
            processScroll();
        }, minScrollTime);
    }
});
Run Code Online (Sandbox Code Playgroud)

这将立即触发第一个滚动事件,然后在滚动条移动时每100ms大约一次滚动事件,然后在滚动条停止移动后获得一个最终事件.您可以通过将参数更改为setTimeout(当前设置为100)来调整事件的频率.

这里有一个演示:http://jsfiddle.net/jfriend00/EBEqZ/,你需要打开调试控制台窗口,开始在内容窗口中移动滚动条,然后在调试控制台窗口中观察每个滚动事件的时间.在我的Chrome版本中,它们的最小间距设置为100毫秒,它们似乎每100-200毫秒就会出现一次.


Hol*_*loW 11

来自jQuery的创建者John Resig有一个很酷的解释来解决这种情况.

var outerPane = $details.find(".details-pane-outer"),
    didScroll = false;

$(window).scroll(function() {
    didScroll = true;
});

setInterval(function() {
    if ( didScroll ) {
        didScroll = false;
        // Check your page position and then
        // Load in more results
    }
}, 250);
Run Code Online (Sandbox Code Playgroud)

来源:http: //ejohn.org/blog/learning-from-twitter/


Ala*_*ras 8

var isWorking = 0;

$(window).on('scroll', function()
{
    if(isWorking==0)  
    {
         isWorking=1;
         if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
         # load more content via ajax
         setTimeout(function(){isWorking=0},1000);
    }
}
Run Code Online (Sandbox Code Playgroud)


A. *_*rel 7

var now = new Date().getTime();
$(window).scroll( function () {
    if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
    {
        if (new Date().getTime() - now > 1000)
        {
            console.log("Task executed once per second");
            now = new Date().getTime();
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

要么

您可以使用Throttling fonction调用: throttling-function-calls

function throttle(fn, threshhold, scope) {
  threshhold || (threshhold = 250);
  var last,
      deferTimer;
  return function () {
    var context = scope || this;

    var now = +new Date,
        args = arguments;
    if (last && now < last + threshhold) {
      // hold on to it
      clearTimeout(deferTimer);
      deferTimer = setTimeout(function () {
        last = now;
        fn.apply(context, args);
      }, threshhold);
    } else {
      last = now;
      fn.apply(context, args);
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

你可以这样称呼它:

$('body').on('mousemove', throttle(function (event) {
  console.log('tick');
}, 1000));
Run Code Online (Sandbox Code Playgroud)

  • 请在此代码中添加一些注释和说明. (2认同)

mat*_*aly 5

这是一个不需要使用额外的JS库或插件的解决方案,其目的是简化操作。它可能没有其他实现那么有效,但是绝对比每次滚动时触发主事件都要快。

摘自Danny Van Kooten的这篇博客文章。我onscroll()在博客上使用“后退”按钮来延迟事件的时间。

var timer;
$(window).scroll(function() {
    if(timer) {
        window.clearTimeout(timer);
    }
    timer = window.setTimeout(function() {
       // actual code here. Your call back function.
    console.log( "Firing!" );
    }, 100);
});
Run Code Online (Sandbox Code Playgroud)

您还可以通过将变量移出回调函数来避免不必要的重新计算(例如$(window).height(),某些静态div元素的值或高度在页面加载后不会更改)来进一步提高性能。

这是一个根据我的用例改编的示例。

var scrollHeight = $("#main-element").height(); //never changes, no need to recalculate.
$(window).on('scroll', function() {
    if (timer) 
        window.clearTimeout(timer);
    timer = window.setTimeout(function() {
        var scrollPosition = $(window).height() + $(window).scrollTop();    
        if ($(window).scrollTop() < 500)
            $(".toggle").fadeIn(800);
        else 
            $(".toggle").fadeOut(800);
    }, 150); //only fire every 150 ms.
});
Run Code Online (Sandbox Code Playgroud)

这将实际功能限制为仅每150ms执行一次,否则,如果未经过150ms,则将计时器重置为0。调整价值以适应您的需求。