← Назад к вопросам
В чем разница между Throttle и Debounce в JavaScript?
1.7 Middle🔥 151 комментариев
#Node.js и JavaScript#Кэширование и производительность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между Throttle и Debounce в JavaScript
Краткий ответ
Debounce откладывает выполнение функции на N миллисекунд после последнего события. Throttle ограничивает частоту выполнения функции — вызывает её максимум один раз за N миллисекунд. Оба используются для оптимизации и экономии ресурсов.
Debounce — ждёшь паузы
// Ждём, пока пользователь закончит печатать
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Пример: поиск при вводе
const search = debounce((query) => {
console.log('Searching for:', query);
fetch(`/api/search?q=${query}`);
}, 500);
input.addEventListener('input', (e) => {
search(e.target.value);
});
// Пользователь печатает: а → аб → абв → (ждёт 500ms) → запрос
Когда использовать:
- Поиск в реальном времени
- Валидация форм
- Автосохранение
- API запросы при изменении
Throttle — вызываешь регулярно
// Вызывай функцию максимум один раз за N миллисекунд
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// Пример: отслеживание скролла
const handleScroll = throttle(() => {
console.log('Scroll event');
updateProgressBar();
}, 1000);
window.addEventListener('scroll', handleScroll);
// За 3 секунды прокрутки будет ~3 вызова вместо 60+
Альтернативная реализация (trailing edge):
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function(...args) {
if (!lastRan) {
func.apply(this, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if (Date.now() - lastRan >= limit) {
func.apply(this, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
Когда использовать:
- Обработка событий скролла
- Изменение размера окна (resize)
- Движение мыши
- Игровые события (обновление позиции)
Наглядное сравнение
Пользователь щёлкает мышкой 5 раз за 1 секунду:
║─────────────────────────────────────────────║
║ События: │ │ │ │ │ │ │ │ │ │ (10 кликов) ║
║─────────────────────────────────────────────║
Наивный подход:
✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ (10 вызовов)
Debounce (300ms):
✓ (1 вызов — когда пользователь перестал кликать)
Throttle (300ms):
✓ ✓ ✓ ✓ (4 вызова равномерно)
Практические примеры
1. Поиск с debounce
const searchUsers = async (query) => {
const response = await fetch(`/api/users?q=${query}`);
return response.json();
};
const debouncedSearch = debounce(searchUsers, 300);
searchInput.addEventListener('input', (e) => {
debouncedSearch(e.target.value);
});
2. Скролл с throttle
const updateProgressBar = throttle(() => {
const progress = (window.scrollY / (document.height - window.innerHeight)) * 100;
progressBar.style.width = progress + '%';
}, 100);
window.addEventListener('scroll', updateProgressBar);
3. Автосохранение с debounce
const saveFormData = debounce(async (data) => {
await fetch('/api/save', { method: 'POST', body: JSON.stringify(data) });
console.log('Saved!');
}, 1000);
form.addEventListener('change', () => {
saveFormData(new FormData(form));
});
4. Resize обработка с throttle
const handleResize = throttle(() => {
console.log('Window resized');
redrawChart();
}, 200);
window.addEventListener('resize', handleResize);
Использование в Node.js (Express, Socket.io)
const express = require('express');
const { throttle } = require('lodash');
const logTraffic = throttle(() => {
console.log('Traffic check');
}, 5000);
app.use((req, res, next) => {
logTraffic();
next();
});
// Socket.io — throttle mouse events с клиента
socket.on('mousemove', throttle((position) => {
io.emit('cursor', position);
}, 50));
Библиотеки
- Lodash:
_.debounce(),_.throttle() - Underscore.js: аналогично
- Простая реализация: встроить свою (как выше)
Вывод
- Debounce — для действий, которые должны произойти один раз после паузы
- Throttle — для действий, которые должны происходить регулярно, но не чаще N раз в секунду
- Выбор зависит от сценария использования
- Оба метода критичны для оптимизации производительности