Журнал • знания • практикаПоиск по сайту

Сайты, дизайн и самостоятельная работа

Найти материал →

Обработка ошибок в javascript: как показать пользователю понятное сообщение

6 минут чтения

Обработка ошибок в javascript: как показать пользователю понятное сообщение

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

Что проверить перед показом ошибки пользователю

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

Откуда приходит ошибка: исключение, ответ сервера или сбой сети

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

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

В обработке ошибок в JavaScript важно различать ошибку выполнения и неуспешный HTTP-ответ: fetch обычно не отклоняет промис только потому, что сервер вернул статус ошибки. Статус нужно проверить отдельно через response.ok.

Как отделить технические детали от понятного сообщения

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

Не показывайте пользователю напрямую error.message или тело ответа сервера: там могут оказаться внутренние детали. Вместо этого сопоставляйте известные причины с короткими сообщениями, например "Не удалось сохранить изменения. Попробуйте ещё раз" или "Проверьте адрес электронной почты".

function getUserMessage(error) {
  if (error?.kind === "network") {
    return "Не удалось связаться с сервером. Проверьте соединение и попробуйте ещё раз.";
  }

  if (error?.kind === "validation") {
    return "Проверьте введённые данные.";
  }

  return "Не удалось выполнить действие. Попробуйте позже.";
}

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

try {
  await saveChanges();
} catch (error) {
  logger.error("Не удалось сохранить изменения", error);
  showMessage(getUserMessage(error));
}

Какие состояния интерфейса подготовить для неудачного запроса

Перед изменением интерфейса проверьте подготовку:

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

Затем настройте обработку по шагам:

  1. Покажите состояние ожидания.
    Пока запрос выполняется, дайте понять, что действие принято, и временно предотвратите случайную повторную отправку.
  2. Проверьте результат ответа.
    После получения ответа проверьте response.ok и обработайте ожидаемые статусы, например ошибку проверки данных.

    • Для исправляемых данных покажите, какое поле нужно проверить.
    • Для недоступности сервера предложите повторить действие позже.
  3. Поймайте сбой запроса.
    Используйте try/catch, чтобы обработать исключение или ошибку сети и не оставлять интерфейс в состоянии ожидания.
  4. Покажите безопасный текст.
    Подберите сообщение по типу ошибки, не выводя внутренний текст исключения или необработанный ответ сервера.
  5. Верните интерфейс в рабочее состояние.
    Снимите индикатор загрузки, сохраните введённые данные и оставьте доступным подходящий следующий шаг.
async function submitForm(data) {
  setLoading(true);

  try {
    const response = await fetch("/api/profile", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data)
    });

    if (!response.ok) {
      if (response.status === 400) {
        showMessage("Проверьте введённые данные.");
        return;
      }

      throw new Error("Request failed");
    }

    showMessage("Изменения сохранены.");
  } catch (error) {
    logger.error("Ошибка при сохранении профиля", error);
    showMessage("Не удалось сохранить изменения. Попробуйте ещё раз.");
  } finally {
    setLoading(false);
  }
}

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

Как обработать ошибки в async/await и цепочках промисов

JavaScript try catch обработка ошибок сработает для исключений внутри соответствующего блока и для отклонённых промисов, если перед ними стоит await. В цепочке промисов используйте .catch() или возвращайте ошибку дальше - не оставляйте отклонённый промис без обработчика.

  • Проверяется ли response.ok после вызова fetch.
  • Есть ли обработчик для каждого промиса, который может завершиться ошибкой.
  • Не проглатывается ли ошибка без сообщения или записи в журнал.
  • Снимается ли состояние загрузки в finally.
  • Не отображается ли пользователю необработанный error.message.
  • Сохраняются ли введённые данные после неудачной отправки.
  • Обрабатываются ли отмена запроса и другие ожидаемые сценарии отдельно от неожиданных сбоев.

В обработчике промиса сохраняйте тот же принцип:

fetch("/api/items")
  .then((response) => {
    if (!response.ok) {
      throw new Error("Request failed");
    }
    return response.json();
  })
  .then((items) => renderItems(items))
  .catch((error) => {
    logger.error("Не удалось загрузить список", error);
    showMessage("Не удалось загрузить список. Попробуйте позже.");
  });

Если пользователь отменил запрос, не обязательно показывать уведомление: достаточно вернуть интерфейс в ожидаемое состояние. Ошибку отмены не следует смешивать с сетевым сбоем.

Когда повторять запрос, а когда предложить другое действие

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

Сообщение должно описывать конкретный следующий шаг. Например: "Не удалось загрузить список. Проверьте соединение и повторите попытку" информативнее, чем "Ошибка".

Как проверить сообщения на понятность и безопасность

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

  • Текст рядом с полем. Уместен для ошибок ввода: укажите, что проверить именно в этом поле.
  • Уведомление в интерфейсе. Подходит для сбоя действия, если пользователю нужно быстро увидеть сообщение и выбрать следующий шаг.
  • Незаметная обработка. Используйте для ожидаемых фоновых событий, которые не требуют внимания; технический сбой при этом можно записать в журнал.
  • Обращение в поддержку. Предложите этот вариант, если пользователь не может самостоятельно устранить проблему; не включайте в сообщение секреты или внутренние данные.

Чтобы вывести сообщение об ошибке пользователю JavaScript-приложения безопасно, используйте текст из заранее подготовленных вариантов и выводите его как текст, а не как HTML-разметку. Это снижает риск случайно отобразить недоверенное содержимое ответа сервера как разметку. Проверяйте сообщения на понятность и для случаев, когда запрос завершился успешно, но данные требуют внимания.

Разбор неоднозначных ситуаций при показе ошибок

Нужно ли показывать пользователю текст исключения?

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

Почему fetch не попадает в catch при ответе с ошибкой?

Потому что неуспешный HTTP-статус сам по себе обычно не отклоняет промис fetch. Проверяйте response.ok и обрабатывайте статус отдельно.

Когда сетевой сбой можно не показывать?

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

Можно ли показать ответ сервера целиком?

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

Что делать, если запрос отменён?

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

Нужно ли автоматически повторять неудачный запрос?

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

Scroll to Top