Debounce
Функция вызовется только после паузы: серия событий схлопывается в один вызов в конце.
1function debounce(fn: () => void, delayMs: number): () => void {2 let timer: ReturnType<typeof setTimeout> | undefined3 4 return () => {5 if (timer !== undefined) clearTimeout(timer)6 7 timer = setTimeout(() => {8 timer = undefined9 fn()10 }, delayMs)11 }12}Проблема
Пользователь печатает в поисковой строке, тащит слайдер, ресайзит окно — каждое движение порождает десятки событий. Слать запрос на каждый — значит заспамить сервер и получить гонку ответов. Нужен вызов только когда события закончились.
Что вы видите
Таймлайн с точками-событиями и «окном тишины». Каждое новое событие перезапускает таймер — окно сдвигается. Когда окно догорает без новых событий — срабатывает вызов. Пять событий, один вызов.
Как это работает
Debounce возвращает обёртку, которая при каждом вызове сбрасывает предыдущий таймер и ставит новый на delay мс. Реальный вызов происходит только если за delay мс не случилось ничего нового. Это «ожидание тишины»: полезно для поиска по мере ввода, автосохранения, ресайза.
Пошаговый разбор
- 01
Событие
Обёртка вызвана: clearTimeout предыдущего таймера.
- 02
Новый таймер
setTimeout(fn, delay) — окно тишины отсчитывается заново.
- 03
Серия
Каждое следующее событие до истечения delay снова перезапускает таймер.
- 04
Тишина
delay прошёл без событий — fn() наконец вызывается один раз.
Complexity и ограничения
Задержка подбирается по сценарию: поиск — 300 мс, автосейв — 1000 мс. Таймер надо чистить при unmount.
Edge cases
- Бесконечный поток событий
Если события приходят чаще delay, fn не вызовется никогда — для такого нужен throttle.
- Одно событие
Вызов ровно один, через delay.
- Unmount
Незачищенный таймер вызовет fn после размонтирования компонента — утечка.
Где встречается в реальности
Поиск с подсказками
Запрос уходит после того, как пользователь перестал печатать.
Автосохранение
Сохраняем черновик через секунду после последнего изменения.
Resize-вычисления
Дорогой пересчёт раскладки — один раз, когда окно перестало менять размер.
Связанные алгоритмы
«5 событий — 1 запрос. Как не заспамить сервер»
Тот же сценарий StepSequence в вертикальной композиции — с safe zones и записью WebM ниже на странице.
Shorts 9:16
Вертикальная композиция строится той же последовательностью шагов, что и страница: safe zones отмечены пунктиром (там живёт UI платформ), биты сценария подсвечиваются по прогрессу. Кнопка записи сохраняет WebM — детерминированная StepSequence даёт воспроизводимый ролик без монтажа.