Исключения – один из немногих примеров удачного использования наследования. В этом уроке мы научимся создавать свои исключения и перехватывать их.
Обычно исключения используются так. Ближе к началу программы стоит конструкция try/catch, которая ловит исключения и показывает пользователю адекватное сообщение:
try {
doSomethingDangerous();
} catch (e) {
console.log(e);
}
Но как понять что случилось? Иногда это важно. Разные ошибки могут приводить к разному поведению программы. Кроме того, не все ошибки требуют обработки в текущем месте программы.
Разделять ошибки можно с помощью разных классов наследующихся от класса Error.
// Такой способ работает, только если не используется Babel
class MyError extends Error {}
class AnotherError extends MyError {}
Причем в отличие от других примеров наследования, в исключениях редко нужно добавлять или изменять поведение. Основная цель использования наследования исключений – описание всех возможных типов ошибок.
Теперь посмотрим как этим можно воспользоваться:
try {
// Какой-то код, который может выбросить исключение
} catch (e) {
if (e instanceof MyError)
// Делаем что-нибудь одно
else if (e instanceof AnotherError) {
// Делаем что-нибудь другое
}
// Во всех остальных случаях, например, бросаем исключение снова
throw e;
}
Перехват любого базового исключения автоматически влечет за собой перехват всех наследников текущего класса. Например, если в блоке catch перехватывать MyError, то этот блок поймает объекты этого класса и объекты всех наследников.
Практически в любом языке программирования есть негласное правило о том, как работать с иерархиями исключений. Любая программа должна определять свое собственное высокоуровневое исключение, которое наследуется от Error. Все остальные исключения библиотеки наследуются от него. Такой подход позволяет изолировать обработку ошибок конкретной библиотеки буквально одним блоком catch.
Но не все библиотеки в JavaScript используют наследование. Дело в том, что до стандарта es6 не было классов и простого способа создания "наследников" от конструктора Error. И, так как многие библиотеки все еще реализуются на старом стандарте, они решают проблему определения типа ошибки с помощью обычного свойства:
import axios from 'axios';
try {
client.get('https://ru.hexlet.io');
} catch (e) {
if (e.isAxiosError) {
// Сюда попадут все ошибки библиотеки axios
}
// обработка остальных ошибок
}
В некоторых ситуациях бывает нужно продолжить работу независимо от того, возникло исключение или нет. Используя только try/catch, эту задачу нельзя выполнить без дублирования. Придется размещать код как после всей конструкции try/catch, так и в каждом блоке catch.
Это привело к тому, что саму конструкцию расширили, добавив в нее блок finally. Этот блок вызывается в самом конце и в любом случае:
try {
// Какой-то код
} catch (e) {
// Делаем что-нибудь одно
} finally {
// Вызовется в любом случае
}
Вам ответят команда поддержки Хекслета или другие студенты.
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
Наши выпускники работают в компаниях:
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Зарегистрируйтесь или войдите в свой аккаунт