Начало и завершение образуют разные порядки
Взаимодействие с сетью выполняется асинхронно. Пока одна операция ожидает ответ, приложение может начать другую. Запрос А для лампы отправлен раньше запроса Б для стола, но сервер или сеть могут обработать их с разной задержкой. Если каждый обработчик безусловно записывает полученные данные в один список, результат определяется порядком завершения. Ключевой вопрос здесь иной: соответствует ли ответ текущему намерению пользователя. Простое ожидание внутри одной асинхронной функции не устанавливает общий порядок для нескольких независимо запущенных вызовов этой функции.
Актуальность можно представить номером поколения
Рассмотрим учебную модель: при каждом новом поиске увеличивается общий номер поколения. Запрос запоминает номер, с которым начался. Перед изменением видимого списка обработчик сравнивает сохранённый номер с текущим. У запроса А номер один, у Б номер два. Когда приходит Б, номер совпадает, и результат допускается к отображению. Поздний ответ А имеет старый номер и уже не должен заменять список. При этом сами полученные данные не обязательно ошибочны: они просто относятся к прежнему запросу. Правило касается также сообщения об ошибке и индикатора загрузки, иначе старый обработчик способен нарушить уже корректное состояние.
Отмена и проверка состояния решают связанные задачи
Для отмены ожидания сетевого запроса браузер предоставляет механизм AbortController. Сигнал передают операции, а при отмене требуется корректно обработать соответствующее исключение. Отмена помогает прекратить ненужную работу на стороне клиента, но логика актуальности остаётся отдельной частью проектирования: к моменту отмены данные могли уже перейти к дальнейшей обработке. Полезно также отличать ошибку сети от серверного ответа с ошибочным статусом. Успешное получение объекта ответа само по себе не означает успешность прикладного запроса. В учебном интерфейсе каждый переход проверяют с учётом текущего поколения, статуса ответа и состояния экрана.
Попробуйте на практике
Смоделируйте гонку запросов на бумаге. Устанавливать инструменты, обращаться к серверу и писать исполняемый код не требуется.
- Нарисуйте временную линию: начало А для лампы, начало Б для стола, завершение Б, завершение А. Отметьте, какой поисковый текст сейчас введён пользователем.
- Проследите вариант без проверки актуальности: каждый ответ заменяет список. Запишите, что окажется на экране после последнего события и почему это расходится с текущим запросом.
- Назначьте поколения один и два. Для каждого завершения сравните номер ответа с текущим номером и отметьте, разрешено ли изменять список.
- Добавьте альтернативный исход: А завершился ошибкой уже после успешного Б. Определите, должен ли старый обработчик показывать ошибку поверх результата для стола. Проверьте таким же способом выключение индикатора загрузки.
Как проверить результат. В защищённой модели на экране остаются результаты для стола, а поздний ответ или ошибка А не изменяют состояние нового поиска. В разборе явно различаются время завершения и право операции обновлять интерфейс.
Частые вопросы
Достаточно ли замедлить отправку запросов?
Ограничение частоты может уменьшить число операций, но не доказывает правильный порядок оставшихся ответов. Проверку актуальности рассматривают отдельно от частоты запуска.
Нужно ли игнорировать любой старый результат?
Для видимого списка текущего поиска он устарел. Другие способы использования, например хранение в отдельном кэше, требуют собственной явно заданной логики и не должны незаметно менять актуальный экран.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.