Что такое оптимизация поиска с дебаунсом
Что проверяют
Понимаете ли вы, что дебаунс это не просто «поменьше запросов», а компромисс с двумя ценами: задержкой ответа и гонкой ответов. Фронтендера спрашивают об этом, потому что живой поиск делали все, а доводили до конца немногие.
Как отвечать
Дебаунс откладывает вызов: на каждом новом событии таймер сбрасывается, и функция срабатывает только после паузы в вводе.
function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}Дальше самое важное, чего обычно не говорят:
- откладывать нужно запрос, а не состояние поля. Значение в контролируемом вводе обновляется сразу, иначе интерфейс подтормаживает на каждой букве;
- задержка подбирается на слух, порядка четверти секунды. Короткая не экономит ничего, длинная ощущается как залипание;
- дебаунс не решает гонку. Два запроса всё равно могут вернуться не в том порядке, поэтому нужен
AbortControllerили проверка, что пришедший ответ соответствует последнему введённому значению; - пустой ввод должен отменять запрос, а не искать пустую строку;
- в React функция создаётся один раз, через
useMemoили ссылку. Созданная в теле компонента она пересоздаётся на каждый рендер, и дебаунса фактически нет. Таймер снимается при размонтировании.
Отличие от троттлинга: дебаунс ждёт тишины, троттлинг пропускает не чаще раза в интервал. Для поиска нужен первый, для обработчика прокрутки второй.
Где спотыкаются
Оборачивают в дебаунс само обновление значения поля. Курсор скачет, символы появляются рывками, и пользователь получает интерфейс медленнее, чем был без всякой оптимизации.
Создают обёртку прямо в теле компонента. На каждый рендер рождается новый таймер, старый никто не сбрасывает, и запросы уходят так же часто, как раньше, только теперь с задержкой.
Останавливаются на экономии запросов и забывают про порядок ответов. Медленный ответ по короткой строке приходит последним и затирает актуальный результат, а выглядит это как случайно мигающая выдача.