Як створити помилку вручну
Щоб створити помилку вручну, пишемо throw new Error("текст помилки"). Конструктор створює об'єкт помилки, а оператор throw запускає механізм обробки винятків і шукає найближчий try...catch.
Теорія
TL;DR
new Error("текст")створює об'єкт помилки, сам по собі він нічого не перериває.throwкидає цей виняток і перериває виконання поточного блоку.- Рушій шукає найближчий
try...catch; знайшов, помилка потрапляє туди, не знайшов, програма падає. - Крім
ErrorєTypeError,RangeError,ReferenceError,SyntaxErrorта інші нащадки. - Свій тип помилки роблять через
class ValidationError extends Error.
Швидкий приклад
try {
throw new Error("Something went wrong!");
} catch (err) {
console.log("caught:", err.message);
}Вивід:
caught: Something went wrong!Як це працює
new Error("текст")створює об'єкт помилки з полямиname,messageіstack.throwкидає (генерує) цей виняток.- JavaScript перериває виконання поточного блоку і шукає найближчий
try...catch. - Якщо обробник знайдено, помилка «потрапляє» туди. Якщо ні, програма завершується з повідомленням про помилку.
Важливо розділяти два кроки: new Error(...) без throw просто створить об'єкт і нічого не перерве.
const err = new Error("just an object"); // nothing happens yet
throw err; // now the exception is raisedВалідація вхідних даних
Найчастіший сценарій ручного кидання помилки, це перевірка аргументів:
function divide(a, b) {
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("Arguments must be numbers!");
}
if (b === 0) {
throw new Error("Division by zero is not allowed!");
}
return a / b;
}
try {
console.log(divide(10, 0));
} catch (e) {
console.log("Error:", e.message);
}Вивід:
Error: Division by zero is not allowed!Зверніть увагу: для неправильного типу беремо TypeError, для порушеної бізнес-умови, базовий Error.
Вбудовані типи помилок
Кидати можна не лише Error, а й його нащадків:
throw new TypeError("Wrong type");
throw new RangeError("Value is out of range");
throw new ReferenceError("Undefined variable");Усі вони створюються однаково, через new ...Error("повідомлення"), і всі успадковані від Error, тож instanceof Error для них дає true.
Власний клас помилки
Можна створити свій тип помилки, успадкувавши його від Error:
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError("Name is required!");
}
}
try {
validateUser({});
} catch (e) {
console.log(`${e.name}: ${e.message}`);
}Вивід:
ValidationError: Name is required!Окремий клас зручний тим, що в catch його можна відрізнити від інших помилок через instanceof ValidationError і обробити інакше.
Кидати можна будь-що, але краще не треба
Формально throw приймає будь-яке значення:
throw "an arbitrary string";
throw 404;
throw { message: "failure", code: 123 };Так робити не рекомендується: такі значення не мають ані stack, ані name, ламають звичний формат помилок і роблять код менш передбачуваним. Завжди краще:
throw new Error("Message");І пам'ятайте, що throw без обробника зупиняє програму:
throw new Error("Critical failure!");
console.log("this line never runs");Вивід:
Uncaught Error: Critical failure!Інструменти в одному місці:
| Що використовуємо | Призначення |
|---|---|
throw | Кидає виняток |
Error | Базовий клас помилок |
TypeError, RangeError, ReferenceError | Спеціалізовані типи помилок |
try...catch | Обробляє помилку |
class CustomError extends Error | Створення власних помилок |
Типові помилки
- Писати
new Error("...")безthrowі дивуватися, що виконання йде далі. - Кидати рядки або числа замість об'єктів
Error, через це вcatchнемає ніstack, ніname. - Забувати
super(message)у власному класі помилки, тодіmessageлишиться порожнім. - Не ставити
this.nameу власному класі, і в логах помилка виглядатиме як звичайнийError. - Кидати помилку всередині
catchбез зовнішньогоtry...catch, такий виняток уже ніхто не спіймає.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.