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

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

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

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

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

我的问题是

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

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

【问题讨论】:

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

标签: javascript jquery javascript-events


【解决方案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


    正如Esailijahis 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/>");  
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 2016-07-15
      • 1970-01-01
      • 2019-02-01
      相关资源
      最近更新 更多