Отмена валидации

Валидация в Vest строится вокруг декларативных наборов правил (suites), которые выполняются последовательно или с учётом асинхронных проверок. В реальных приложениях часто возникает необходимость прервать текущий процесс валидации: при смене состояния формы, повторном вводе данных, переключении шага мастера или устаревании входных значений. Отмена валидации в этом контексте означает прекращение выполнения текущего набора проверок с гарантией, что результаты уже запущенных асинхронных операций не повлияют на итоговое состояние.

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

Причины необходимости отмены

Валидационные сценарии в пользовательских интерфейсах часто подвержены гонкам состояний:

  • пользователь вводит данные быстрее, чем завершается проверка
  • несколько параллельных запусков валидации одной формы
  • устаревание данных при смене шага или вкладки
  • асинхронные запросы к серверу проверки (email, username, уникальность)

Без механизма отмены возможна ситуация, когда более ранняя проверка завершится позже и перезапишет более актуальный результат.

Базовая модель отмены выполнения

Внутри архитектуры Vest валидация представляется как функция, которая может быть повторно вызвана. Каждый запуск формирует отдельный контекст исполнения. Отмена заключается в инвалидации этого контекста.

Типовой подход строится на следующих принципах:

  • каждый запуск валидации получает уникальный идентификатор
  • все проверки «помечаются» этим идентификатором
  • при запуске новой валидации предыдущий идентификатор становится недействительным
  • результаты проверок игнорируются, если контекст устарел

Такой механизм позволяет не останавливать физически уже запущенные промисы, но исключать их влияние.

AbortController как основа отмены

В современных реализациях JavaScript наиболее универсальный механизм отмены асинхронных операций — AbortController. Он используется для сигнализации о необходимости прервать выполнение:

  • HTTP-запросов
  • таймаутов и задержек
  • пользовательских асинхронных проверок

В связке с Vest это позволяет интегрировать отмену на уровне асинхронных тестов:

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

Отмена асинхронных проверок

Асинхронные тесты являются основным источником необходимости отмены. Пример логики:

  • запускается проверка доступности email
  • пользователь изменяет email до завершения запроса
  • запускается новая проверка
  • результат старого запроса приходит позже и становится неактуальным

Чтобы избежать этого, каждая проверка должна учитывать контекст актуальности:

  • проверка перед возвратом результата сверяет текущий идентификатор запуска
  • при несовпадении результат игнорируется
  • либо проверка завершается через AbortSignal

Такой подход предотвращает состояние гонки без необходимости отменять сетевые запросы на уровне инфраструктуры.

Контроль жизненного цикла валидации

Жизненный цикл валидации включает несколько фаз:

  1. Инициация запуска
  2. Создание контекста выполнения
  3. Выполнение синхронных тестов
  4. Запуск асинхронных проверок
  5. Сбор результатов
  6. Финализация состояния

Отмена может происходить на разных этапах:

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

Особенность заключается в том, что синхронные тесты не могут быть «отменены» в классическом смысле — они выполняются мгновенно. Поэтому отмена здесь реализуется через прекращение дальнейшего выполнения цепочки.

Конкурентные запуски и инвалидация

При частых изменениях формы может происходить параллельный запуск нескольких валидаций. Без механизма инвалидации результаты смешиваются.

Подход с версионированием контекста:

  • validationVersion = n
  • каждый новый запуск увеличивает версию
  • тесты «захватывают» текущую версию при старте
  • при завершении сравнивают её с актуальной
  • несовпадение означает устаревший результат

Это обеспечивает детерминированность итогового состояния.

Отмена через ранний выход из suite

Структура suite в Vest позволяет управлять порядком выполнения тестов. Отмена может быть реализована как ранний выход из цепочки:

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

Это особенно важно для каскадных форм, где ошибка в одном поле делает бессмысленной проверку остальных.

Асинхронные гонки и защита результатов

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

  • A: запрос отправлен
  • B: запрос отправлен позже
  • B завершился первым
  • A завершился позже и перезаписал результат

Защита реализуется через:

  • проверку актуальности контекста перед установкой результата
  • привязку результата к идентификатору запуска
  • игнорирование устаревших промисов

Таким образом, даже без физической отмены запросов система остаётся консистентной.

Интеграция отмены в пользовательские сценарии

В интерфейсах с высокой частотой обновлений отмена становится критическим механизмом:

  • автокомплит полей
  • live-валидация
  • формы с динамическими правилами
  • многошаговые сценарии

При каждом изменении значения старый процесс валидации становится неактуальным. Отмена предотвращает накопление лишних вычислений и снижает нагрузку на асинхронные ресурсы.

Ограничения механизма отмены

Несмотря на эффективность, отмена валидации имеет ограничения:

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

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

Комбинирование стратегий отмены

В реальных реализациях применяется комбинация подходов:

  • AbortController для асинхронных операций
  • versioning для контроля актуальности
  • ранний выход для синхронных тестов
  • игнорирование устаревших результатов

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