简体   繁体   English

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

[英]How to limit handling of event to once per X seconds with jQuery / javascript?

For a rapidly-firing keypress event, I want to limit the handling of the event to a maximum of once per X seconds. 对于快速触发的keypress事件,我希望将事件的处理限制为每X秒最多一次。

I'm already using jQuery for the event handling, so a jQuery-based solution would be preferred, though vanilla javascript is fine too. 我已经在使用jQuery进行事件处理,所以基于jQuery的解决方案会更受欢迎,尽管vanilla javascript也很好。

  • This jsfiddle shows keypress firing rapidly without any limiting on the handling 这个jsfiddle快速显示按键触发,不受任何操作限制

  • This jsfiddle implements limiting the handling to once per 0.5 seconds in vanilla JS using setTimeout() 这个jsfiddle使用setTimeout()实现将vanilla JS中的处理限制为每0.5秒一次

My question is 我的问题是

  1. Does jQuery have an inbuilt way of doing this? jQuery有内置的方法吗? I don't see anything in the .on() docs 我在.on() 文档中没有看到任何内容

  2. If not, is there a better pattern for doing this in vanilla JS than I've used in my second jsfiddle example ? 如果没有,在我的第二个jsfiddle例子中使用vanilla JS有没有更好的模式呢?

Does jQuery have an inbuilt way of doing this? jQuery有内置的方法吗?

No. 没有。

If not, is there a better pattern for doing this in vanilla JS than I've used in my second jsfiddle example? 如果没有,在我的第二个jsfiddle例子中使用vanilla JS有没有更好的模式呢?

Instead of using setTimeout and flags, you can keep track of when the handler was called the last time and only call it after a defined interval has passed. 您可以跟踪上次调用处理程序的时间,而只是在定义的时间间隔过后调用它,而不是使用setTimeout和flags。 This is referred to as throttling and there are various ways to implement this. 这被称为限制,并且有各种方法来实现这一点。

In its simplest form you just have to ignore every call that is made within the time of lastCall + interval , so that only one call in every interval occurs. 在最简单的形式中,您只需忽略在lastCall + interval时间内进行的每个调用,以便每个间隔中只发生一次调用。

Eg here is a function that returns a new function which can only be called once every X milliseconds: 例如,这是一个返回一个新函数的函数,该函数每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);
        }
    };
}

which you can use as 你可以用作

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

DEMO DEMO


As Esailija mentions in his comment , maybe it is not throttling that you need but debouncing . 正如Esailija他的评论中提到的那样,也许你不需要扼杀 ,而是要贬值 This is a similar but slightly different concept. 这是一个类似但略有不同的概念。 While throttling means that something should occur only once every x milliseconds, debouncing means that something should occur only if it didn't occur in the last x milliseconds. 虽然限制意味着某些事情应该每x毫秒只发生一次,但是去抖动意味着只有在最后x毫秒内没有发生某些事情时才会发生。

A typical example is the scroll event. 典型的例子是scroll事件。 A scroll event handler will be called very often because the event is basically triggered continuously. 将经常调用滚动事件处理程序,因为事件基本上是连续触发的。 But maybe you only want to execute the handler when the user stopped scrolling and not while he is scrolling. 但也许你只想要执行的处理程序,当用户停止滚动,而不是他滚动。

A simple way to achieve this is to use a timeout and cancel it if the function is called again (and the timeout didn't run yet): 实现此目的的一种简单方法是使用超时并在再次调用该函数时取消它(并且超时尚未运行):

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

A drawback with this implementation is that you cannot return a value from the event handler (such as return false; ). 此实现的缺点是您无法从事件处理程序返回值(例如return false; )。 Maybe there are implementations which can preserve this feature (if required). 也许有些实现可以保留此功能(如果需要)。

DEMO DEMO

I would do that event throttling as simple as this: 我会做那个事件限制就像这样简单:

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

记录上次处理事件的时间,并且每次收到事件时,都要检查是否已经过了所需的时间间隔。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM