Поиск по каталогу спортивного инвентаря с задержкой ввода

Поле поиска и отфильтрованный каталог спортивных предметов на экране

Задержка ввода объединяет частые изменения в один запуск после небольшой паузы. Она полезна, когда обновление действительно заметно по стоимости. Для четырёх строк задержка не нужна ради скорости; здесь она добавлена как учебный пример, чтобы отделить сам поиск от планирования вызова.

Локальный поиск с отменяемым таймером

index.html

<!doctype html>
<html lang="ru"><meta charset="utf-8"><title>Поиск инвентаря</title>
<label for="query">Поиск по названию</label><input id="query" type="search">
<p id="count" aria-live="polite"></p><ul id="results"></ul>
<script>
const products = ['Мяч футбольный', 'Мяч баскетбольный', 'Коврик', 'Эспандер'];
const input = document.querySelector('#query');
const list = document.querySelector('#results');
function search(items, query) {
  const normalized = query.trim().toLocaleLowerCase('ru-RU');
  return items.filter(x => x.toLocaleLowerCase('ru-RU').includes(normalized));
}
function debounce(fn, delay) {
  let timer;
  return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), delay); };
}
function render(query) {
  const found = search(products, query);
  list.replaceChildren(...found.map(text => {
    const li = document.createElement('li'); li.textContent = text; return li;
  }));
  document.querySelector('#count').textContent = `Найдено: ${found.length}`;
}
const delayedRender = debounce(render, 250);
input.addEventListener('input', () => delayedRender(input.value));
render('');
</script></html>

Введите «мяч»: после короткой паузы останутся две строки. Быстро изменяйте запрос — прежний таймер отменяется. В обработчик передаётся уже прочитанная строка, а не объект события, состояние которого не стоит использовать как позднее хранилище ввода. Задержка 250 мс условная и не является универсальной нормой.

Механизмы, которые не нужно смешивать
Что сравнить На что смотреть Что сделать
Поиск Отбор по нормализованной строке Тестируется синхронно
Debounce Отложить до паузы Отменяет предыдущий таймер
Throttle Ограничить частоту в потоке Имеет другой контракт
Сетевой запрос Получить данные извне Требует защиты от устаревших ответов

Пустой запрос должен иметь определённый смысл

В примере пустая строка показывает все товары. Это осознанное правило: includes пустой строки сработает для каждого названия. Для другого продукта можно показать начальное состояние или подсказку. Не оставляйте это случайным побочным эффектом, особенно если дальнейшая версия будет отправлять запросы на сервер.

  • Проверить пробелы вокруг запроса.
  • Проверить разный регистр букв.
  • Быстро ввести и стереть несколько символов.
  • Проверить запрос без совпадений.

Debounce не решает гонку сетевых ответов. Если ранний запрос возвращается позже нового, нужен отдельный идентификатор актуальности или отмена с корректной обработкой. Также при удалении компонента может потребоваться отменить таймер. Не выдавайте этот локальный пример за законченный серверный поиск или средство безопасности.

Вопросы и ответы

Почему поиск не запускается на keydown?

input отражает изменение значения, включая способы ввода, которые не сводятся к обычной клавише.

Нужно ли всегда делать задержку?

Нет. Проверяйте удобство и стоимость обновления. Заметная ненужная пауза может ухудшить интерфейс.

Как тестировать debounce?

Контролировать время и проверять число вызовов после серии вводов, а не ждать случайного поведения руками.

Покроет ли includes все языковые особенности?

Нет. Это простое правило подстроки. Морфология и сложная нормализация требуют отдельной задачи.

Похожие записи