如何使用jQuery / javascript将事件处理限制为每X秒一次?

Posted

技术标签:

【中文标题】如何使用jQuery / javascript将事件处理限制为每X秒一次?【英文标题】:How to limit handling of event to once per X seconds with jQuery / javascript? 【发布时间】:2013-08-13 04:26:35 【问题描述】:

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

我已经在使用 jQuery 进行事件处理,因此最好使用基于 jQuery 的解决方案,尽管原生 javascript 也可以。

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

This jsfiddle 使用 setTimeout() 实现将处理限制为每 0.5 秒一次。

我的问题是

    jQuery 有内置的方法吗?我在.on() docs 没有看到任何内容

    如果没有,有没有比我在 second jsfiddle example 中使用的更好的模式在 vanilla JS 中执行此操作?

【问题讨论】:

您可能需要考虑使用 keyup 代替,除非您有某些理由想要重复。 code.google.com/p/jquery-debounce hnldesign.nl/blog/debouncing-events-with-jquery @zerkms 谢谢,我真的很想在没有插件的“纯”jQuery 中做到这一点,但这非常有帮助 - 考虑推广回答,这样我就可以投票了! @davnicwil:仅链接的答案是一件无聊的事情,我没有心情重新表述链接中已经提供的内容:-) 如果您只想获取用户在文本字段中输入的数据,在他完成输入后,您可以使用“更改”事件 【参考方案1】:

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

【讨论】:

【参考方案2】:

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));

DEMO


正如Esailija 在his comment 中提到的,您可能需要的不是节流,而是去抖动。这是一个类似但略有不同的概念。 节流意味着某事应该每 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;)返回值。也许有些实现可以保留此功能(如果需要)。

DEMO

【讨论】:

这不是节流吗?我认为 debounce 意味着只要呼叫在一定的毫秒内进入,就继续移动超时,并且在事情稳定下来时才最终拨打一个电话。也许我有其他方式...... 好吧,它似乎没有节流,也没有去抖动..根据这个解释drupalmotion.com/article/… :P 或者它可能是节流......啊,但它绝对没有去抖动 @davnicwil 它还有助于确定您的应用程序做了什么,因为去抖动可能更合适。例如,我从来不需要在 js 中进行节流......假设您每次按键都发送 ajax 请求。然后,当用户仍在键入时,限制会浪费请求。 @Esailija:事件是在一系列事件的开始时触发的,而不是在事件结束时触发的。见jsfiddle.net/mKx2K/7。也许没有setTimeout也有办法做到这一点,但我目前想不出一个(时间不早了,我该睡觉了;))。 @davnicwil:很多研究都涉及到人类的用户体验和反应时间,每两个发生在大约 100 毫秒间隔内的事件都被认为是同时发生的。 IE。不能分开。您可以将其称为 hack 或者您可以将其称为应用科学 ;) 无论如何,不​​客气! :)【参考方案3】:

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

$("#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/>");  
);

【讨论】:

以上是关于如何使用jQuery / javascript将事件处理限制为每X秒一次?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用javascript触发jquery事件?

如何使用 JavaScript/JQuery 创建一个简单的地图 [重复]

如何在 jQuery 选择器中使用 JavaScript 变量?

如何使用 JavaScript 或 jQuery 更改数组内对象的值?

如何使用 JavaScript 或 jquery 选中/取消选中复选框?

如何使用 Javascript/jQuery 确定图像是不是已加载?