Обработка исключений¶
В JavaScript есть класс Error
, который можно использовать для исключений. Вы выбрасываете ошибку с ключевым словом throw
. Вы можете отловить её с помощью блоков try
/ catch
, например:
1 2 3 4 5 |
|
Подтипы ошибок¶
Помимо встроенного класса Error
, существует несколько дополнительных встроенных классов ошибок, которые наследуются от Error
, которые может генерировать среда выполнения JavaScript:
RangeError¶
Создается экземпляр ошибки, которая возникает, когда числовая переменная или параметр выходит за пределы допустимого диапазона.
1 2 3 |
|
ReferenceError¶
Создается экземпляр ошибки, которая возникает при разыменовании недействительной ссылки. Например:
1 2 |
|
SyntaxError¶
Создается экземпляр ошибки, возникающей при синтаксическом анализе кода, который не является допустимым в JavaScript.
1 |
|
TypeError¶
Создается экземпляр ошибки, которая возникает, когда переменная или параметр имеет недопустимый тип.
1 |
|
URIError¶
Создается экземпляр ошибки, которая возникает, когда в encodeURI()
или decodeURI()
передаются недопустимые параметры.
1 |
|
Всегда используйте Error
¶
Начинающие разработчики JavaScript иногда просто бросают необработанные строки, например.
1 2 3 4 5 |
|
Не делайте так. Основное преимущество объектов Error
состоит в том, что автоматически отслеживается где они были созданы и произошли с помощью свойства stack
.
Необработанные строки приводят к очень болезненной отладке и затрудняют анализ ошибок из логов.
Вам не нужно выбрасывать
ошибку¶
Это нормально передавать объект Error
. Это общепринятый код в Node.js колбэк стиле, который принимает колбэк первым параметром как объект ошибки.
1 2 3 4 5 6 7 8 9 |
|
Исключительные случаи¶
Исключения должны быть исключительными
- это частая поговорка в компьютерных науках. Это одинаково справедливо и для JavaScript (и для TypeScript) по нескольким причинам.
Неясно откуда брошено исключение¶
Рассмотрим следующий фрагмент кода:
1 2 3 4 5 6 |
|
Следующий разработчик не знает, какая функция может вызвать ошибку. Человек, просматривающий код, не может знать об этом, не прочитав код для task1 / task2 и других функций, которые они могут вызвать внутри себя и т.д.
Делает поэтапную обработку сложной¶
Вы можете попытаться сделать обработку поэтапной с помощью явного отлова вокруг каждого места, которое может бросить ошибку:
1 2 3 4 5 6 7 8 9 10 |
|
Но теперь, если вам нужно передать что-то из первой задачи во вторую, код становится грязным: (обратите внимание на мутацию foo
, требующую let
+ явную необходимость описывать ее, потому что это не может быть логически выведено от возврата runTask1
):
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Не очень хорошо отражено в системе типов¶
Рассмотрим функцию:
1 2 3 4 |
|
Использование Error
для таких случаев - плохая идея, так как ошибка не отражена в определении типа для проверки функции (value:number) => void
. Вместо этого лучший способ создать метод проверки:
1 2 3 4 |
|
И теперь это отражено в системе типов.
Если вы не хотите обрабатывать ошибку очень общим (простым / универсальным и т.д.) способом, не бросайте ошибку.