В JavaScript часто возникает необходимость контролировать частоту
выполнения функций, особенно при обработке событий с высокой
интенсивностью, таких как scroll, resize или
input. Для этих целей применяются техники
debounce и throttle. Они помогают
снизить нагрузку на браузер, предотвращая чрезмерное срабатывание
обработчиков.
Debounce задерживает выполнение функции до тех пор, пока не прекратятся повторные вызовы в течение определённого интервала времени. Другими словами, функция будет вызвана только один раз после того, как поток событий утихнет.
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}
Пояснение работы:
timeoutId хранит идентификатор текущего
таймера.clearTimeout.delay.Применение:
input).const searchInput = document.querySelector('#search');
const fetchResults = debounce((query) => {
console.log(`Ищем: ${query}`);
}, 300);
searchInput.addEventListener('input', (e) => fetchResults(e.target.value));
Throttle ограничивает частоту выполнения функции, разрешая её вызов не чаще одного раза в заданный интервал времени, независимо от того, сколько раз произошло событие.
function throttle(func, limit) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= limit) {
lastCall = now;
func.apply(this, args);
}
};
}
Пояснение работы:
lastCall хранит время последнего выполнения
функции.limit миллисекунд с
момента последнего выполнения.Применение:
scroll) для показа
анимаций.resize).window.addEventListener('scroll', throttle(() => {
console.log('Прокрутка с ограничением частоты');
}, 200));
| Характеристика | Debounce | Throttle |
|---|---|---|
| Поведение | Выполняется один раз после затишья | Выполняется регулярно с фиксированным интервалом |
| Применение | Ввод текста, автозавершение, валидация | Скролл, ресайз, анимации |
| Интенсивность вызова | Низкая, только после окончания событий | Средняя, ограниченный поток вызовов |
| Контроль нагрузки | Хороший для нерегулярных действий | Хороший для постоянных событий |
Tippy.js — библиотека для создания тултипов в веб-интерфейсах. При динамическом взаимодействии (например, hover по множеству элементов или обновление содержимого тултипов) важно оптимизировать производительность с помощью debounce и throttle.
Пример с debounce для динамического контента тултипа:
import tippy from 'tippy.js';
const input = document.querySelector('#username');
tippy(input, {
content: 'Введите имя пользователя',
onShow(instance) {
updateTooltip(instance);
}
});
const updateTooltip = debounce((instance) => {
const value = input.value;
instance.setContent(value ? `Вы ввели: ${value}` : 'Введите имя пользователя');
}, 300);
Пример с throttle для отслеживания движения мыши:
document.addEventListener('mousemove', throttle((e) => {
const tooltipElements = document.querySelectorAll('.tooltip');
tooltipElements.forEach(el => {
const tip = el._tippy;
if (tip) {
tip.setContent(`Координаты: ${e.clientX}, ${e.clientY}`);
}
});
}, 100));
В обоих случаях используется контроль частоты вызова функций, чтобы сократить нагрузку на DOM и избежать лагов интерфейса, что особенно важно при использовании Tippy.js для динамических тултипов.
this) и аргументы функции
сохраняются через apply.delay для debounce, limit для
throttle) подбираются эмпирически, исходя из частоты
события и требуемой отзывчивости интерфейса.В сложных интерфейсах можно комбинировать debounce и throttle:
const input = document.querySelector('#search');
tippy(input, {
content: 'Поиск...',
onShow(instance) {
const update = debounce(() => {
instance.setContent(`Результаты для: ${input.value}`);
}, 300);
update();
}
});
Такой подход обеспечивает плавность интерфейса, снижает нагрузку на браузер и сохраняет высокую отзывчивость интерфейса при динамических изменениях.