В JavaScript при работе с событиями пользовательского интерфейса
часто возникает необходимость контролировать частоту вызова
функций. Особенно это актуально для событий, которые
срабатывают очень часто: scroll, resize,
mousemove, input. Без ограничения частоты
вызовов функции может происходить чрезмерное потребление ресурсов и
падение производительности. Для решения этой задачи применяются
throttle и debounce.
Debounce — это метод, который задерживает выполнение функции до тех пор, пока событие не прекратит поступать на протяжении заданного интервала времени. Проще говоря, функция будет вызвана только один раз после того, как события прекратятся.
Принцип работы:
Пример реализации debounce:
function debounce(func, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
Использование с SortableJS:
SortableJS генерирует множество событий во время перетаскивания
элементов, например, onMove или onUpdate. Если
выполнять сложную логику при каждом событии, это может тормозить
интерфейс. Применение debounce позволяет:
const list = document.getElementById('items');
Sortable.create(list, {
onUpdate: debounce((evt) => {
console.log('Список обновлен', evt.oldIndex, '->', evt.newIndex);
// Дополнительные действия, например, сохранение порядка на сервере
}, 300)
});
В этом примере функция срабатывает только через 300 мс после окончания перемещений, что снижает нагрузку на обработку.
Throttle ограничивает количество вызовов функции в единицу времени. Функция будет вызываться не чаще одного раза в заданный интервал, даже если событие срабатывает постоянно.
Принцип работы:
Пример реализации throttle:
function throttle(func, limit) {
let inThrottle;
return function (...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
Использование с SortableJS:
При обработке событий onMove или onChange
throttle позволяет ограничить обновление состояния приложения:
const list = document.getElementById('items');
Sortable.create(list, {
onMove: throttle((evt) => {
console.log('Элемент перемещается', evt.dragged, evt.related);
}, 100)
});
Здесь обработчик выполняется не чаще одного раза в 100 мс, что делает интерфейс плавным и отзывчивым.
| Характеристика | Debounce | Throttle |
|---|---|---|
| Время вызова | После прекращения событий | С интервалом, даже при непрерывных событиях |
| Применение | Поисковые строки, автосохранение формы | Скролл, drag & drop, ресайз |
| Поведение при спаме событий | Срабатывает один раз | Срабатывает периодически |
Ключевой момент: debounce подходит, когда важен конечный результат, а throttle — когда важна регулярность обновлений.
SortableJS предоставляет следующие события, где throttle и debounce особенно полезны:
onMove — срабатывает при каждом движении элемента.
Часто используется с throttle, чтобы контролировать
визуальные эффекты или логику интерфейса.onUpdate — срабатывает при окончательном изменении
порядка элементов. Часто используется с debounce, чтобы
выполнять операции один раз после завершения перетаскивания.onStart и onEnd — события начала и
завершения drag-and-drop. Здесь throttle/debounce редко нужны, так как
события происходят редко.Пример комбинирования:
Sortable.create(list, {
onMove: throttle((evt) => {
console.log('Throttled move event', evt.dragged);
}, 50),
onUpdate: debounce((evt) => {
console.log('Debounced update event', evt.oldIndex, evt.newIndex);
}, 200)
});
Такой подход снижает нагрузку на браузер при больших списках и делает интерфейс отзывчивым.
leading,
trailing вызовы).Throttle и debounce являются ключевыми инструментами оптимизации производительности в интерфейсах с высокой частотой событий. В контексте SortableJS правильное их использование позволяет обрабатывать перетаскивание элементов эффективно, без задержек и «тормозов» при визуализации или обновлении данных.