Как ограничить обработку события один раз в X секунд с помощью jQuery / javascript?

для быстрой стрельбы keypress событие, я хочу ограничить обработку события максимум один раз за X секунд.

Я уже использую jQuery для обработки событий, поэтому предпочтительным было бы решение на основе jQuery, хотя vanilla javascript тоже хорош.

  • этот jsfiddle показывает нажатие клавиши стрельбы быстро без каких-либо ограничений на обработку

  • этот jsfiddle реализует ограничение обработки один раз в 0,5 секунды в vanilla JS с помощью setTimeout()

у меня вопрос

  1. есть ли у jQuery встроенный способ сделать это? Я ничего не вижу в .on() docs

  2. Если нет, есть ли лучший шаблон для этого в vanilla JS, чем я использовал в своем второй пример jsfiddle?

3 ответов


есть ли у 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));

демо


As Esailija упоминает в комментарии, может быть, это не дросселирование, что вам нужно, но debouncing. Это аналогичная, но несколько иная концепция. В то время как регулирование означает, что что-то должно происходить только раз в x миллисекунд, debouncing означает, что что-то должно произойти, только если это не произошло за последние 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;). Возможно, есть реализации, которые могут сохраните эту функцию (при необходимости).

демо


Я бы сделал это дросселирование событий так просто:

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

запись когда в последний раз вы обработали событие было, и каждый раз, когда вы получаете событие, сделать проверку, чтобы увидеть, если интервал истек.