Полный цикл в digital

Типы ошибок

В блоке catch мы можем получить информацию об ошибке, которая представляет объект. Все ошибки, которые генерируются интерретатором JavaScript, предоставляют объект типа Error который имеет ряд свойств:

  • message сообщение об ошибке
  • name тип ошибки

Стоит отметить, что отдельные браузеры поддерживают еще ряд свойств, но их поведение в зависимости от браузера может отличаться:

  • fileName название файла с кодом JavaScript, где произошла ошибка
  • lineNumber строка в файле, где произошла ошибка
  • columnNumber столбец в строке, где произошла ошибка
  • stack стек ошибки

Получим данные ошибки, например, при вызове несуществующей функции:

try{
callSomeFunc();
}
catch(error){
console.log("Тип ошибки:", error.name);
console.log("Ошибка:", error.message);
}

Консольный вывод:

Тип ошибки: ReferenceError
Ошибка: callSomeFunc is not defined

Типы ошибок

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

  • EvalError представляет ошибку, которая генерируется при выполнении глобальной функции eval()
  • RangeError ошибка генерируется, если параметр или переменная, представляют число, которое находится вне некотоого допустимого диапазона
  • ReferenceError ошибка генерируется при обращении к несуществующей ссылке
  • SyntaxError представляет ошибку синтаксиса
  • TypeError ошибка генерируется, если значение переменной или параметра представляют некорректный тип или пр попытке изменить значение, которое нельзя изменять
  • URIError ошибка генерируется при передаче функциям encodeURI() и decodeURI() некорректных значений
  • AggregateError предоставляет ошибку, которая объединяет несколько возникших ошибок

Например, при попытке присвоить константе второй раз значение, генерируется ошибка TypeError:

try{
const num = 9;
num = 7;
}
catch(error){
// TypeError
console.log(error.name);  
// Assignment to constant variable.
console.log(error.message);  
}

Применение типов ошибок

При генерации ошибок мы можем использовать встроенные типы ошибок:

class Person{
constructor(name, age){
if(age < 0) throw new Error("Возраст должен быть положительным");
this.name = name;
this.age = age;
}
print(){ console.log(`Name: ${this.name}  Age: ${this.age}`);}
}
try{
const tom = new Person("Tom", -45);
tom.print();
}
catch(error){   
// Возраст должен быть положительным
console.log(error.message);  
}

Здесь конструктор класса Person принимает значения для имени и возаста человека. Если передан отрицательный возраст, то генерируем ошибку в виде объекта Error. В качестве параметра в конструктор Error передается сообщение об ошибке:

if(age < 0) throw new Error("Возраст должен быть положительным");

В итоге при обработке исключения в блоке catch мы сможем получить переданное сообщение об ошибке. Все остальные типы ошибок в качестве первого параметра в конструкторе также принимают сообщение об ошибке. Сгенерируем несколько типов ошибок:

class Person{
constructor(pName, pAge){
const age = parseInt(pAge);
if(isNaN(age))  throw new TypeError("Возраст должен представлять число");
if(age < 0 || age > 120) throw new RangeError("Возраст должен быть больше 0 и меньше 120");
this.name = pName;
this.age = age;
}
print(){ console.log(`Name: ${this.name}  Age: ${this.age}`);}
}

Поскольку для возраста можно ередатьне только число, но и вообще какое угодно значение, то вначале мы пытаемся преобразовать это значение в число с помощью функции parseInt():

const age = parseInt(pAge);
if(isNaN(age))  throw new TypeError("Возраст должен представлять число");

Далее с помощью функции isNaN(age) проверяем, является полученное число числом. Если age - не число, то данная функция возвращает true. Поэтому генерируется ошибка типа TypeError.

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

if(age < 0 || age > 120) throw new RangeError("Возраст должен быть больше 0 и меньше 120");

Проверим генерацию исключений:

try{
const tom = new Person("Tom", -45);
}
catch(error){   
// Возраст должен быть больше 0 и меньше 120
console.log(error.message); 
}
try{
const bob = new Person("Bob", "bla bla");
}
catch(error){   
// Возраст должен представлять число
console.log(error.message); 
}
try{
const sam = new Person("Sam", 23);
// Name: Sam  Age: 23
sam.print();    
}
catch(error){   
console.log(error.message);
}

Консольный вывод:

Возраст должен быть больше 0 и меньше 120
Возраст должен представлять число
Name: Sam  Age: 23

Обработка нескольких типов ошибок

При выполнении одного и то же кода могут генерироваться ошибки разных типов. И иногда бывает необходимо разграничить обработку разных типов. В этом случае мы можем проверять тип возникшей ошибки. Например, пример выше с классом Person:

class Person{
constructor(pName, pAge){
const age = parseInt(pAge);
if(isNaN(age))  throw new TypeError("Возраст должен представлять число");
if(age < 0 || age > 120) throw new RangeError("Возраст должен быть больше 0 и меньше 120");
this.name = pName;
this.age = age;
}
print(){ console.log(`Name: ${this.name}  Age: ${this.age}`);}
}
try{
const tom = new Person("Tom", -45);
const bob = new Person("Bob", "bla bla");
}
catch(error){   
if (error instanceof TypeError) {
console.log("Некорректный тип данных.");
} else if (error instanceof RangeError) {
console.log("Недопустимое значение");
}
console.log(error.message);
}

Создание своих типов ошибок

Мы не ограничены встроенными только встроенными типами ошибок и при необходимости можем создавать свои типы ошибок, предназначеные для каких-то конкретных ситуаций:

class PersonError extends Error {
constructor(value, ...params) {
// остальные параметры передаем в конструктор базового класса
super(...params)
this.name = "PersonError"
this.argument = value;
}
}
class Person{
constructor(pName, pAge){
const age = parseInt(pAge);
if(isNaN(age))  throw new PersonError(pAge, "Возраст должен представлять число");
if(age < 0 || age > 120) throw new PersonError(pAge, "Возраст должен быть больше 0 и меньше 120");
this.name = pName;
this.age = age;
}
print(){ console.log(`Name: ${this.name}  Age: ${this.age}`);}
}
try{
//const tom = new Person("Tom", -45);
const bob = new Person("Bob", "bla bla");
}
catch(error){   
if (error instanceof PersonError) {
console.log("Ошибка типа Person. Некорректное значение:", error.argument);
}
console.log(error.message);
}

Консольный вывод:

Ошибка типа Person. Некорректное значение: bla bla
Возраст должен представлять число

Для представления ошибки класса Person здесь определен тип PersonError, который наследуется от класса Error:

class PersonError extends Error {
constructor(value, ...params) {
// остальные параметры передаем в конструктор базового класса
super(...params)
this.name = "PersonError"
this.argument = value;
}
}

В конструкторе мы определяем дополнительное свойство - argument. Оно будет хранить значение, которое вызвало ошибку. С помощью параметра value конструктора получаем это значение. Кроме того, переопреляем имя типа с помощью свойства this.name.

В классе Person используем этот тип, передавая в конструктор PersonError соответствующие значения:

if(isNaN(age))  throw new PersonError(pAge, "Возраст должен представлять число");
if(age < 0 || age > 120) throw new PersonError(pAge, "Возраст должен быть больше 0 и меньше 120");

Затем при обработки исключения мы можем проверить тип, и если он представляет класс PersonError, то обратиться к его свойству argument:

catch(error){   
if (error instanceof PersonError) {
console.log("Ошибка типа Person. Некорректное значение:", error.argument);
}
console.log(error.message);
}
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг