Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Исключения JS: Погружаясь в классы

Исключения — один из немногих примеров удачного использования наследования. В этом уроке мы научимся создавать свои исключения и перехватывать их.

Обычно исключения используются так. Ближе к началу программы стоит конструкция try/catch, которая ловит исключения и показывает пользователю адекватное сообщение:

try {
  doSomethingDangerous();
} catch (e) {
  console.log(e);
}

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

Разделять ошибки можно с помощью разных классов наследующихся от класса Error.

// Такой способ работает, только если не используется Babel
class MyError extends Error {}
class FirstError extends MyError {}
class SecondError extends MyError {}

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

Теперь посмотрим как этим можно воспользоваться. В теории мы можем написать такой код:

try {
  // Какой-то код, который может выбросить исключение
} catch (e) {
  if (e instanceof MyError) {
    // Обрабатываем MyError
  } else if (e instanceof FirstError) {
    // Обрабатываем FirstError
  } else if (e instanceof SecondError) {
    // Обрабатываем SecondError
  }

  // Во всех остальных случаях, например, бросаем исключение снова
  throw e;
}

Обработка любого базового исключения автоматически влечет за собой обработку всех наследников текущего класса. Например, если в блоке catch перехватывать в условии MyError, то этот блок поймает объекты этого класса и объекты всех наследников. Если будет перехвачена ошибка класса FirstError, то блок с проверкой FirstError никогда не выполнится, так как условие e instanceof MyError в первом блоке будет истинным в этом случае. То же самое будет и с SecondError. Чтобы избежать такого поведения, мы можем поставить проверку FirstError и SecondError перед MyError, либо делать проверку имени класса e.constructor.name === 'FirstError'.

Практически в любом языке программирования есть негласное правило о том, как работать с иерархиями исключений. Любая программа должна определять свое собственное высокоуровневое исключение, которое наследуется от Error. Все остальные исключения библиотеки наследуются от него. Такой подход позволяет изолировать обработку ошибок конкретной библиотеки буквально одним блоком catch.

Но не все библиотеки в JavaScript используют наследование. Дело в том, что до стандарта es6 не было классов и простого способа создания «наследников» от конструктора Error. И, так как многие библиотеки все еще реализуются на старом стандарте, они решают проблему определения типа ошибки с помощью обычного свойства:

import axios from 'axios';

try {
  client.get('https://ru.hexlet.io');
} catch (e) {
  if (e.isAxiosError) {
    // Сюда попадут все ошибки библиотеки axios
  }

  // обработка остальных ошибок
}

Блок finally

В некоторых ситуациях бывает нужно продолжить работу независимо от того, возникло исключение или нет. Используя только try/catch, эту задачу нельзя выполнить без дублирования. Придется размещать код как после всей конструкции try/catch, так и в каждом блоке catch.

Это привело к тому, что саму конструкцию расширили, добавив в нее блок finally. Этот блок вызывается в самом конце и в любом случае:

try {
  // Какой-то код
} catch (e) {
  // Делаем что-нибудь одно
} finally {
  // Вызовется в любом случае
}

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля
профессия
от 9 900 ₽ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

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