简体   繁体   中英

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.

I'm already using jQuery for the event handling, so a jQuery-based solution would be preferred, though vanilla javascript is fine too.

  • This jsfiddle shows keypress firing rapidly without any limiting on the handling

  • This jsfiddle implements limiting the handling to once per 0.5 seconds in vanilla JS using setTimeout()

My question is

  1. Does jQuery have an inbuilt way of doing this? I don't see anything in the .on() docs

  2. If not, is there a better pattern for doing this in vanilla JS than I've used in my second jsfiddle example ?

Does jQuery have an inbuilt way of doing this?

No.

If not, is there a better pattern for doing this in vanilla JS than I've used in my second jsfiddle example?

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. 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.

Eg here is a function that returns a new function which can only be called once every X milliseconds:

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


As Esailija mentions in his comment , maybe it is not throttling that you need but debouncing . 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.

A typical example is the scroll event. 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; ). Maybe there are implementations which can preserve this feature (if required).

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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