Как стать автором
Обновить

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

Время на прочтение2 мин
Количество просмотров58K
Декораторы функций позволяют добавить дополнительное поведение функции, не изменяя ее. Сигнатура оригинальной и декорированной функции полностью совпадают.


Debouncing


Если дословно переводить — «устранение дребезга». Такой декоратор позволяет превратить несколько вызовов функции в течение определенного времени в один вызов, причем задержка начинает заново отсчитываться с каждой новой попыткой вызова. Возможно два варианта:
  1. Реальный вызов происходит только в случае, если с момента последней попытки прошло время, большее или равное задержке.
  2. Реальный вызов происходит сразу, а все остальные попытки вызова игнорируются, пока не пройдет время, большее или равное задержке, отсчитанной от времени последней попытки.

Использование


debouncedFn = $.debounce(fn, timeout, [invokeAsap], [context]);
  • fn — оригинальная функция
  • timeout — задержка
  • invokeAsap — true/false, по умолчанию false. Параметр, указывающий какой из вышеперечисленных вариантов debouncing нужно использовать (по умолчанию используется первый)
  • context — контекст оригинальной функции

Пример использования


Например, у вас есть suggest. Посылать запросы к серверу на каждый keyup расточительно и не нужно. Можно декорировать обработчик, чтобы он срабатывал только после того, как пользователь перестал нажимать на клавиши, допустим, в течение 300 миллисекунд:
function onKeyUp() { ... };

$('input[name=suggest]').keyup($.debounce(onKeyUp, 300));


* This source code was highlighted with Source Code Highlighter.

Или у вас есть один обработчик на несколько событий, и нужно, чтобы если в течение некоторого времени происходит оба события, обработчик срабатывал только на последнем произошедшем событии:
$('input').bind('keyup blur', $.debounce(process, 300));

* This source code was highlighted with Source Code Highlighter.

Throttling


Данный декоратор позволяет «затормозить» функцию — функция будет выполняться не чаще одного раза в указанный период, даже если она будет вызвана много раз в течение этого периода. Т.е. все промежуточные вызовы будут игнорироваться.

Использование


throttledFn = $.throttle(fn, period, [context]);
  • fn — оригинальная функция
  • period — период
  • context — контекст оригинальной функции

Пример использования


Например, на resize окна (или, допустим, на mousemove) у вас срабатывает какой-то тяжелый обработчик. Можно его «затормозить»:
$(window).resize($.throttle(doComplexСomputation, 300));
В итоге, функция будет выполняться не чаще, чем раз в 300 миллисекунд.

Мои реализации этих декораторов в виде jQuery-плагина можно скачать с code.google.

Ps. Навеяно книжкой Николаса Закаса «Professional JavaScript for Web Developers, 2nd Edition», хотя в ней он путает debounce и throttle, называя первое вторым. На ajaxian тоже поднималась эта тема.
Теги:
Хабы:
Всего голосов 74: ↑72 и ↓2+70
Комментарии28

Публикации

Истории

Работа

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
14 сентября
Конференция Practical ML Conf
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн