Микропаттерны оптимизации в Javascript: декораторы функций debouncing и throttling

Javascript, патерны, JQuery

by Denis Tverdokhlebov

HTML

<h2>Микропаттерны оптимизации в Javascript: декораторы функций debouncing и throttling</h2>
<p>Декораторы функций позволяют добавить дополнительное поведение функции, не изменяя ее. Сигнатура оригинальной и декорированной функции полностью совпадают.</p>
<h3>Debouncing</h3>
<p>Если дословно переводить — «устранение дребезга». Такой декоратор позволяет превратить несколько вызовов функции в течение определенного времени в один вызов, причем задержка начинает заново отсчитываться с каждой новой попыткой вызова. Возможно два варианта:</p>
<ol>
  <li>Реальный вызов происходит только в случае, если с момента последней попытки прошло время, большее или равное задержке.</li>
  <li>Реальный вызов происходит сразу, а все остальные попытки вызова игнорируются, пока не пройдет время, большее или равное задержке, отсчитанной от времени последней попытки.</li>
</ol>
<h3>Использование</h3>
<p>debouncedFn = $.debounce(fn, timeout, [invokeAsap], [context]);</p>
<ul>
  <li>fn — оригинальная функция</li>
  <li>timeout — задержка</li>
  <li>invokeAsap — true/false, по умолчанию false. Параметр, указывающий какой из вышеперечисленных вариантов debouncing нужно использовать (по умолчанию используется первый)</li>
  <li>context — контекст оригинальной функции</li>
</ul>
<h3>Пример использования</h3>
<p>Например, у вас есть suggest. Посылать запросы к серверу на каждый keyup расточительно и не нужно. Можно декорировать обработчик, чтобы он срабатывал только после того, как пользователь перестал нажимать на клавиши, допустим, в течение 300 миллисекунд:</p>
<div class="demo">
<p>function onKeyUp() { ... };</p>
<p>$('input[name=suggest]').keyup($.debounce(onKeyUp, 300));</p>
<p>* This source code was highlighted with Source Code Highlighter.</p>
</div>
<p>Или у вас есть один обработчик на несколько событий, и нужно, чтобы если в течение некоторого времени происходит оба события, обработчик срабатывал только на последнем произошедшем событии:</p>
<div...

CSS

body {
  padding: 5px 10px;
  text-align: justify;
}
.demo {
  background-color: #fff7d7;
  padding: 20px 20px;
}