7

对于快速触发的keypress事件,我想将事件的处理限制为每X秒最多一次。

我已经在使用 jQuery 进行事件处理,因此基于 jQuery 的解决方案将是首选,尽管 vanilla Javascript 也很好。

  • 这个 jsfiddle显示按键快速触发,对处理没有任何限制

  • 这个 jsfiddle使用 vanilla JS 将处理限制为每 0.5 秒一次setTimeout()

我的问题是

  1. jQuery 有内置的方法吗?我在.on() 文档中看不到任何内容

  2. 如果没有,在 vanilla JS 中执行此操作是否有比我在第二个 jsfiddle 示例中使用的更好的模式?

4

3 回答 3

31

jQuery 有内置的方法吗?

不。

如果没有,在 vanilla JS 中执行此操作是否有比我在第二个 jsfiddle 示例中使用的更好的模式?

setTimeout您可以跟踪上次调用处理程序的时间,并且仅在经过定义的时间间隔后才调用它,而不是使用和标志。这被称为节流,并且有多种方法可以实现这一点。

在最简单的形式中,您只需忽略在 的时间内进行的每个调用lastCall + interval,以便在每个时间间隔内只发生一个调用。

例如,这是一个返回一个新函数的函数,该函数只能每 X 毫秒调用一次:

function throttle(func, interval) {
    var lastCall = 0;
    return function() {
        var now = Date.now();
        if (lastCall + interval < now) {
            lastCall = now;
            return func.apply(this, arguments);
        }
    };
}

您可以将其用作

$("#inputField").on("keypress", throttle(function(event) {
   $("div#output").append("key pressed <br/>");  
}, 500));

演示


正如Esailija他的评论中提到的,也许你需要的不是节流,而是去抖动。这是一个类似但略有不同的概念。节流意味着每 x 毫秒应该只发生一次,而去抖动意味着只有在最后 x 毫秒内没有发生的情况下才会发生。

一个典型的例子就是scroll事件。滚动事件处理程序将被非常频繁地调用,因为该事件基本上是连续触发的。但也许您只想在用户停止滚动时执行处理程序,而不是他滚动时执行。

实现此目的的一种简单方法是使用超时并在再次调用该函数时取消它(并且超时尚未运行):

function debounce(func, interval) {
    var lastCall = -1;
    return function() {
        clearTimeout(lastCall);
        var args = arguments;
        var self = this;
        lastCall = setTimeout(function() {
            func.apply(self, args);
        }, interval);
    };
}

此实现的一个缺点是您无法从事件处理程序(例如return false;)返回值。也许有些实现可以保留此功能(如果需要)。

演示

于 2013-08-11T22:14:10.300 回答
2

我会像这样简单地进行事件限制:

$("#inputField").on("keypress", function(event) {
    var now = Date.now();
    var nt = $(this).data("lastime") || now; 
    if( nt > now ) return;
    $(this).data("lastime", now + 500);  
    $("div#output").append("key pressed <br/>");  
});
于 2013-08-11T22:19:50.963 回答
1

记录您上次处理事件的时间,以及每次收到事件时,请检查您想要的时间间隔是否已过。

于 2013-08-11T22:09:01.793 回答