Откат при ошибке и разрешение конфликтов
Восстанавливайте предыдущее состояние при сбое мутации и корректно обрабатывайте отклонённые сервером оптимистичные изменения
«Откат при ошибке и разрешение конфликтов» — бесплатный урок React Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения React Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс React Academy содержит 4 уроков всего.
Сложность отката растёт вместе с типом мутации
Откат оптимистичного добавления (удаление элемента) или удаления (восстановление элемента) прост. Откат обновления сложнее: необходимо восстановить точное предыдущее значение. Если элемент несколько раз оптимистично обновлялся, нужно отдельно отслеживать каждое предыдущее значение, а не только исходное состояние на сервере.
Сценарий конфликта при обновлении
Рассмотрим такой сценарий: на сервере у элемента значение Z. Вы оптимистично обновляете его до X. Пока ваш запрос выполняется, другой пользователь обновляет тот же элемент на сервере до Y. Ваш запрос поступает на сервер, который отклоняет его из-за конфликта. Цель отката — Z, но текущее состояние на сервере — Y. Восстановление Z ошибочно перезапишет Y.
Безопасный вариант по умолчанию: повторный запрос при ошибке
Самая безопасная стратегия отката при обновлении — заново запросить элемент с сервера при любой ошибке мутации, а не восстанавливать локально сохранённый снимок. Это гарантирует отображение актуального состояния сервера независимо от того, что другие пользователи могли изменить одновременно. Повторный запрос медленнее, но всегда даёт правильный результат.
Статус HTTP 409 «Конфликт»
Хорошо спроектированный API возвращает HTTP 409 «Конфликт», если оптимистичное обновление не удалось из-за параллельного изменения. Тело ответа обычно содержит текущее состояние на сервере. Обработчик ошибок должен обнаружить код 409, использовать тело ответа, чтобы обновить локальное состояние текущим значением с сервера, и уведомить пользователя, что изменения не сохранены.
Идемпотентность для безопасных повторных попыток
Идемпотентная мутация даёт одинаковый результат при многократном применении. Проектирование мутаций как идемпотентных (использование PUT вместо POST, передача полного состояния ресурса и ключей идемпотентности) позволяет безопасно повторять запрос при ошибке, не опасаясь применить изменение дважды. Это значительно упрощает логику отката.
Устранение дубликатов с помощью isSubmitting
Двойной щелчок по кнопке отправки может запустить две одинаковые мутации. Предотвратите это с помощью флага isSubmitting: устанавливайте его в true при начале мутации и сбрасывайте после её завершения — независимо от успеха или ошибки. Отключайте элемент запуска, когда isSubmitting имеет значение true. Это устраняет дублирование мутаций на уровне интерфейса.
Ключи идемпотентности для устранения дубликатов на сервере
Для устранения дубликатов на стороне сервера включайте в каждый запрос мутации уникальный заголовок Idempotency-Key. Генерируйте его с помощью crypto.randomUUID(), когда пользователь инициирует действие. Сервер обнаруживает повторяющиеся ключи и возвращает тот же ответ, что и исходный запрос, не применяя операцию повторно.
Индикаторы итоговой согласованности
Пока мутация выполняется, можно показать ненавязчивый индикатор того, что оптимистичное состояние ещё не подтверждено: небольшую пульсирующую точку, текст «Сохранение…» или слегка уменьшенную непрозрачность элемента. Это сообщает о неопределённости, не блокируя взаимодействие. Уберите индикатор после успешного выполнения или выполните откат при ошибке.
Границы ошибок при сбоях мутаций
Непредвиденные ошибки в логике отката (например, обращение к свойствам неопределённого значения при восстановлении состояния) могут привести к сбою компонента. Оберните компоненты, активно использующие мутации, в границу ошибок, чтобы критические сбои отката отображались в понятном интерфейсе ошибки, а не на пустом экране. Записывайте эти ошибки в журнал для отладки.
Версионирование для обнаружения конфликтов
Надёжная стратегия обнаружения конфликтов: включайте номер версии или ETag в каждую мутацию. Сервер сравнивает версию, отправленную клиентом, с текущей версией. Если они различаются (произошло другое обновление), сервер возвращает 409. Это оптимистичный контроль параллелизма — вы предполагаете отсутствие конфликта, но обнаруживаете его, когда он возникает.
Тестирование сценариев отката
Логику отката часто не тестируют, потому что сбои сети трудно имитировать. Используйте такие инструменты, как средство имитации сетевых запросов MSW, чтобы возвращать ответы с ошибками в тестах. Напишите отдельные тесты для обработки конфликта 409, отката при тайм-ауте сети, устранения дубликатов при двойном щелчке и согласованности состояния после сбоя. Именно в таких пограничных случаях скрываются ошибки.
Статус HTTP для обнаружения конфликтов
Какой код состояния HTTP возвращает хорошо спроектированный API, когда оптимистичное обновление завершается ошибкой из-за параллельного изменения другим пользователем?
Итоги урока: откат и конфликты
Обновление откатывать сложнее, чем добавление или удаление: при ошибке всегда заново запрашивайте данные, чтобы избежать проблем с устаревшим снимком. HTTP 409 «Конфликт» сообщает об ошибках оптимистичного управления параллелизмом; используйте тело ответа, чтобы восстановить текущее состояние сервера. Проектируйте мутации как идемпотентные для безопасных повторных попыток. Предотвращайте повторные срабатывания с помощью isSubmitting и ключей идемпотентности на стороне сервера. Отдельно тестируйте сценарии отката, используя MSW для имитации ошибок.
Часто задаваемые вопросы
Урок «Откат при ошибке и разрешение конфликтов» бесплатный?
Да — полный текст урока «Откат при ошибке и разрешение конфликтов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс React Academy, подпишись на CoddyKit PRO. Курс React Academy содержит 4 уроков всего.
Чему я научусь в уроке «Откат при ошибке и разрешение конфликтов»?
Восстанавливайте предыдущее состояние при сбое мутации и корректно обрабатывайте отклонённые сервером оптимистичные изменения Ты практикуешь React Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать React Academy?
Предыдущий опыт не требуется. React Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Откат при ошибке и разрешение конфликтов»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке React Academy?
Да. Каждый урок React Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Что такое оптимистичный интерфейс и когда его использовать
- Ручная реализация оптимистичных обновлений
- Откат при ошибке и разрешение конфликтов
- Оптимистичные шаблоны с React Query и Zustand