Подход к отображению ошибок в асинхронном вебе

Андрей Шапиро
Андрей Шапиро · 20 апреля 2022
Interaction Designer · Art Director

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

Обычно при асинхронном взаимодействии возникает два типа проблемных ситуаций: 1) не удалось выполнить какой-то конкретный запрос, отвечающий за кусочек интрфейса; 2) не удалось выполнить запрос, ставящий под угрозу работу всего приложения. Выработанный здесь подход отвечает в первую очередь первым ситуациям, однако имеет свой потенциал и для обработки вторых.

Принципы

Заложим несколько принципов для построения решения.

Шаблон процесса

На основе выявленных принципов опишем шаблон процесса, который будет для нас схемой в любой интерфейсной ситуации обработки ошибок при асинхронном взаимодействии.

  1. После подачи команды показать, что а) запрошенное действие стартовало и происходит; б) сообщения о предыдущей неудаче убраны — начата новая фаза жизни.
  2. Подождать в этом состоянии столько времени сколько нужно, чтобы человек заметил. Не менее 300..600 мс, даже если ответ пришёл раньше.
  3. Плавной анимацией возврата к исходному состоянию показать, что действие не удалось.
  4. Принять исходное состояние элемента управления.
  5. В случае необходимости, сообщить почему действие не удалось, расположив текст одним из следующих способов: а) в «бесплатном» свободном месте в пределах элемента, группы, формы; б) в заранее отведенном специальном месте (пример на гифке ниже: вместо текста подсказки, важного на предыдущем этапе); в) /так себе, лучше не применять/ на следующем z-уровне на какое-то время, затем убрать, но дать обнаруживаемый способ прочитать это же сообщение позже.

Пример с терминальной кнопкой

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

Здесь кнопка взяла на себя функцию демонстрации процесса. Это можно было решить по-другому, например, используя стандартную «крутилку» где-то сбоку, однако здесь используется принцип максимального переиспользования уже существующих элементов, и никакого дополнительного пространства не понадобилось.

Сообщение об ошибке выводится только потому, что на него есть место. Если свободного места совсем нет, допустимо опустить сообщение о неисправимой серверной ошибке. Чтобы дать понять человеку, что операция не удалась, достаточно «покачать» кнопкой или добавить к тексту кнопки грусный смайлик — снова принцип переиспользования ресурсов.

Пример с древовидным списком

Здесь уж точно нет места для длинных сообщений. Даже если его запланировать в открывающемся пространстве, текст придётся ютить или сокращать, анимация раскрытия дерева будет более дёрганной. Следуя принятым принципам, показываем анимацией, что действие начато, и обратным ходом анимации что действие не удалось.

В качестве послесловия

В процессе обсуждения статьи внутри компании я понял, что не очевидна или непривычна сама мысль об отсутствии сообщения об ошибке. Но идея именно в том, что текстовое сообщение в этих случаях необязательно. Текст в формулировке «что-то пошло не так» сообщает только три факта: действие закончено, закончено с ошибкой, вы ничего не можете предпринять, кроме перезапуска. Всё это можно передать описанными выше способами без текста.

Вопросы вызвали примеры, в которых, то есть текст, то нет. С текстом у нас есть шанс повысить информативность для человека. В примере выше, текст используется потому что и была возможность его разместить, и этот текст более информативен, чем «что-то пошло не так».

Сравните два посыла по информативности: