webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
JavaScript · Урок 13 из 17

Обработка ошибок

try/catch/finally, правильный throw, свои ошибки и когда ничего не ловить.

Обновлено

Что такое ошибка

Ошибка (исключение) — сигнал, что что-то пошло не так и программа не может нормально продолжать в этой точке. Когда она возникает, JS останавливает текущую функцию и «поднимается» по вызовам, пока кто-то её не поймает. Если никто не поймал → ошибка в консоли, а в React → экран ошибки.

Ошибка — это объект с полями:

  • name — тип (TypeError, HttpError);
  • message — что случилось;
  • stack — где это случилось (цепочка вызовов) — самая полезная информация при отладке;
  • cause (необязательно) — исходная ошибка, которая её вызвала.

Нативные типы ошибок

Тип Когда возникает Пример
TypeError операция над неверным типом undefined.name, 5()
ReferenceError несуществующая переменная / в TDZ используете необъявленную x
SyntaxError невалидный код или JSON JSON.parse('{nope')
RangeError значение вне допустимых пределов new Array(-1)

Ожидаемые и неожиданные ошибки

Самое важное различие:

Ожидаемые Неожиданные
Примеры неверный email, товара нет в наличии, 404 баг, упавший сервер, undefined.x
Как обрабатывать возвращаемыми значениями: { ok: false, error } исключениями: throw
Кто их видит пользователь, с понятным сообщением логи / мониторинг; пользователь видит общее сообщение

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

try / catch / finally

try {
  const data = JSON.parse(raw)       // код, который может бросить ошибку
  render(data)
} catch (error) {
  showToast('Неверные данные')       // выполняется, только если возникла ошибка
} finally {
  setLoading(false)                  // выполняется всегда, с ошибкой или без
}

throw — как бросать правильно

throw new Error('Пользователь не найден')                     // ✓ есть stack trace
throw new Error('Запрос не удался', { cause: originalError })  // ✓ сохраняете причину
throw 'что-то'                                                 // ✗ ни стека, ни типа

Свои ошибки

Когда коду, который ловит, нужно различать типы ошибок:

class HttpError extends Error {
  constructor(status, message) {
    super(message)
    this.name = 'HttpError'
    this.status = status
  }
}

try {
  await api('/users/5')
} catch (e) {
  if (e instanceof HttpError && e.status === 404) return notFound()
  throw e     // что не умеете обработать — бросаете дальше
}

Ошибки в асинхронном коде

async function load() {
  try {
    const res = await fetch('/api')
    if (!res.ok) throw new HttpError(res.status, 'Запрос не удался')
    return await res.json()
  } catch (e) {
    console.error(e)
    return null
  }
}

Отклонённый и непойманный Promise = unhandledrejection. Подробнее — в Async.

Где ловить ошибки — правило

  1. Ловите там, где можете сделать что-то полезное: сообщение пользователю, повтор, запасное значение.
  2. Не ловите «чтобы не упало» — проглоченная ошибка прячет баг.
  3. Никогда не пишите пустой catch {}.
  4. В React / Next: error.tsx — страховочная сетка для того, что проскочило.

Коротко

  • Ошибка = объект с name, message, stack; поднимается, пока её не поймают.
  • Ожидаемые ошибки → возвращаемые значения; неожиданные → throw new Error(...).
  • try/catch/finally; свои ошибки через extends Error; не глотайте ошибки.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.