Отмена запросов

Отмена запросов в Unpoly представляет собой механизм управления конкурентными переходами и загрузками, который предотвращает накопление устаревших сетевых операций. При работе с интерфейсом пользователи часто инициируют несколько действий подряд: клики по ссылкам, отправки форм, фильтры, автодополнение. Каждый такой шаг потенциально создаёт сетевой запрос. Без контроля подобные ситуации приводили бы к состоянию гонок и неконсистентности интерфейса.

Unpoly отслеживает активные запросы и обладает встроенной политикой их отмены. Ключевой принцип: новый запрос может отменить старый, если последний больше не имеет смыслового значения. Например, если пользователь переключает вкладки один за другим, запросы к предыдущим вкладкам становятся неактуальными, и библиотека отменяет их автоматически.

Отмена обычно осуществляется на уровне XMLHttpRequest или fetch, в зависимости от конфигурации. Unpoly использует собственный слой абстракции, чтобы гарантировать консистентное поведение вне зависимости от браузера.

Типы конкурентности

Unpoly различает несколько сценариев конкурентных загрузок:

  1. Навигации — клики по ссылкам, которые загружают новые фрагменты.
  2. Формы — отправки данных, которые также могут загружать фрагменты.
  3. Фоновые запросы — вспомогательные загрузки, например автодополнение.

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

Указание политики отмены

Для управления поведением отмен используются атрибуты:

  • up-follow или up-submit для объявления навигации или отправки формы.
  • up-preload для предзагрузки.
  • Дополнительные модификаторы, например up-target или up-layer, задают место вставки фрагмента, что влияет на правила отмены.

Ключевые политики

up-abortable Позволяет отменять запрос, если он ещё актуален. Обычно применяется для действий пользователя, когда новые события делают предыдущие устаревшими.

up-keep Заставляет запрос завершиться, даже если произошла новая навигация. Такой режим полезен для загрузок, которые нельзя прерывать по смыслу, например сохранение данных.

up-prevent-reload Запрещает перезагрузку фрагмента при совпадении текущего контекста. Не является отменой буквально, но исключает ненужные запросы.

Автоматические отмены при повторных действиях

При повторном клике по ссылке Unpoly отменяет предыдущий запрос и запускает новый. Визуально интерфейс остаётся отзывчивым: индикаторы загрузки переключаются, а старые запросы больше не влияют на состояние DOM.

Такой подход предотвращает состояние «прыгающего интерфейса», когда медленный сервер внезапно возвращает старые данные и затирает новые.

Отмена при смене слоёв

Unpoly поддерживает слои (layers): основной, модальные окна, панели, оверлеи. Правило: запрос привязан к своему слою. Если слой закрывается до завершения загрузки, запрос отменяется, поскольку результат невозможно корректно отобразить.

Такой автоматизм избавляет разработчика от необходимости вручную отслеживать жизненный цикл UI-компонентов.

Обработка ошибок при отмене

Отмена не рассматривается как ошибка. В обычных Promise отменённый запрос приводил бы к отклонённому состоянию, но Unpoly использует собственную модель событий:

  • up:request:aborted — уведомление о прекращении загрузки.
  • up:layer:aborted — отмена из-за закрытия слоя.
  • up:fragment:aborted — отмена рендеринга фрагмента.

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

Взаимодействие с сервером

Сервер обычно не знает о клиентской отмене: HTTP-протокол не гарантирует мгновенное прекращение обработки. Однако отмена на клиенте предотвращает применение устаревшего результата. С точки зрения пользователя это выглядит как мгновенное переключение контента, даже если сервер продолжает обработку.

Если требуется сокращать нагрузку на сервер, можно дополнительно использовать дебаунс или специальную логику отмены на уровне приложений, например через WebSockets, сигналы прерывания или idempotency-токены.

Отмена при нескольких фрагментах

Запрос может обновлять несколько целей (up-target="a, b, c"). Если один из фрагментов становится неактуальным, запрос отменяется целиком. Такой подход сохраняет целостность интерфейса, избегая смешивания старых и новых фрагментов.

Таймауты и ручные отмены

Unpoly позволяет вызвать отмену вручную через API:

  • up.network.abort() — отмена всех текущих запросов.
  • up.network.abort('nav') — отмена навигаций.
  • up.network.abort('form') — отмена отправок.

Для управления временем ответа используются параметры таймаута. При превышении срока запрос также рассматривается как отменённый и не влияет на интерфейс.

Отмена и оптимизация UX

Отмена запросов способствует:

  • снижению визуального шума
  • предотвращению рассинхронизации UI
  • уменьшению задержек при быстром взаимодействии
  • увеличению предсказуемости поведения приложений

В сочетании с индикацией загрузки и слоями отмена становится фундаментальным элементом интерфейсов с высокой частотой действий.

Сигналы отмены и совместимость с fetch

Современные браузеры поддерживают AbortController, и Unpoly использует этот механизм, если доступен. Это обеспечивает корректную отмену на уровне низкоуровневых API и совместимость с потоковой загрузкой фрагментов.

Взаимодействие с кэшем

Если запрос отменён до получения ответа, он не помещается в кэш Unpoly. Это гарантирует, что в кэше хранятся только корректные и завершённые фрагменты. При повторных запросах можно избежать скачков данных.

Отмена при предзагрузке

Предзагрузка (up-preload) отменяется, если потребность в ней отпадает. Например, пользователь навёл курсор на ссылку, но кликнул другую. Это снижает сетевую нагрузку, не нарушая скорость восприятия интерфейса.

На уровне архитектуры

Отмена запросов формирует каркас реактивности в Unpoly. Она делает интерфейсы детерминированными при большой конкуренции событий. Библиотека опирается на следующие принципы:

  • приоритет последних действий
  • смысловая актуальность
  • согласованность слоёв
  • экономия ресурсов
  • предотвращение гонок данных

Эти механизмы позволяют строить современные интерфейсы, где фрагменты обновляются чаще, чем в традиционных страницах, а пользователи выполняют множество действий подряд.