Пошук уроків, статей та іншого контенту
Ознайомитеся з об’єктом Error, його властивостями name, message і stack та стандартними підтипами помилок.
ErrorError — це вбудований об’єкт JavaScript, який описує помилку під час виконання програми.
Об’єкт помилки зазвичай містить:
name — назву типу помилки;
message — пояснення причини помилки;
stack — стек викликів, тобто послідовність функцій, які призвели до помилки.
Помилку можна створити за допомогою конструктора Error:
const error = new Error("Не вдалося завантажити дані");
console.log(error.name); // Error
console.log(error.message); // Не вдалося завантажити дані
console.log(error.stack); // Стек викликівЗа замовчуванням name має значення "Error", а message містить текст, переданий конструктору.
Errornamename містить назву помилки:
const error = new TypeError("Очікувався рядок");
console.log(error.name); // TypeErrorЦя властивість допомагає визначити, до якого типу належить помилка.
messagemessage містить опис помилки:
const error = new Error("Файл не знайдено");
console.log(error.message); // Файл не знайденоПовідомлення має бути зрозумілим і пояснювати, що саме пішло не так.
stackstack містить інформацію про стек викликів. Він допомагає знайти місце, де виникла помилка.
function firstFunction() {
secondFunction();
}
function secondFunction() {
throw new Error("Сталася помилка");
}
firstFunction();У консолі можна побачити приблизно такий стек:
Error: Сталася помилка
at secondFunction (...)
at firstFunction (...)
at ...Формат stack може відрізнятися в різних браузерах і середовищах JavaScript. Ця властивість широко підтримується, але її формат не слід вважати однаковим у всіх середовищах.
Створити об’єкт помилки недостатньо, щоб програма одразу зупинилася. Для цього помилку потрібно викинути за допомогою оператора throw.
const error = new Error("Недостатньо прав");
throw error;Зазвичай об’єкт створюють і викидають одним виразом:
throw new Error("Користувача не знайдено");Після виконання throw JavaScript припиняє поточне виконання коду та шукає обробник цієї помилки.
Оператор throw може викинути будь-яке значення:
throw "Помилка";
throw 404;
throw { message: "Помилка" };Проте рекомендовано викидати об’єкти Error або його підтипів. Вони мають стандартні властивості та корисний стек викликів.
throw new Error("Щось пішло не так");try...catchКонструкція try...catch дає змогу перехопити помилку та виконати запасний сценарій.
try {
throw new Error("Не вдалося виконати операцію");
} catch (error) {
console.log("Виникла помилка:", error.message);
}Код у блоці try виконується першим. Якщо в ньому виникає помилка, виконання переходить до блоку catch.
Параметр error містить об’єкт помилки:
try {
const number = 10;
number.toUpperCase();
} catch (error) {
console.log(error.name);
console.log(error.message);
}Результат буде приблизно таким:
TypeError
number.toUpperCase is not a functionfinallyБлок finally виконується в будь-якому разі:
якщо помилки не було;
якщо помилку було перехоплено;
якщо помилку не перехопили в цьому місці.
try {
console.log("Спроба виконати операцію");
} catch (error) {
console.log("Обробка помилки");
} finally {
console.log("Операцію завершено");
}finally часто використовують для очищення ресурсів або завершення індикатора завантаження.
JavaScript має кілька стандартних підтипів Error. Вони допомагають точніше описати причину проблеми.
ErrorБазовий, загальний тип помилки.
throw new Error("Невідома помилка");Використовуйте його, коли жоден спеціалізований тип не підходить.
TypeErrorTypeError виникає, коли значення має неправильний тип або операція неможлива для цього типу.
const user = null;
user.name;Результатом буде TypeError, оскільки властивість не можна прочитати у null.
Ще один приклад:
const number = 42;
number.toUpperCase();Метод toUpperCase призначений для рядків, а не для чисел.
Власну помилку цього типу можна створити так:
throw new TypeError("Параметр має бути рядком");ReferenceErrorReferenceError виникає, коли програма звертається до змінної, якої не існує в доступній області видимості.
console.log(userName);Якщо змінну userName не було оголошено, JavaScript викине ReferenceError.
try {
console.log(userName);
} catch (error) {
console.log(error.name); // ReferenceError
}SyntaxErrorSyntaxError означає помилку синтаксису — порушення правил написання JavaScript-коду.
Наприклад, у рядку нижче пропущено закривну дужку:
// const numbers = [1, 2, 3;Такі помилки зазвичай виникають ще до запуску програми, тому try...catch не завжди може їх перехопити.
SyntaxError також можна створити вручну:
throw new SyntaxError("Неправильний формат виразу");RangeErrorRangeError виникає, коли значення не належить до допустимого діапазону.
const numbers = new Array(-1);Не можна створити масив із від’ємною кількістю елементів, тому виникне RangeError.
Власний приклад:
function setPercentage(value) {
if (value < 0 || value > 100) {
throw new RangeError("Відсоток має бути від 0 до 100");
}
return value;
}
console.log(setPercentage(50));URIErrorURIError виникає під час використання функцій для роботи з URI, якщо передано некоректне значення.
try {
decodeURIComponent("%");
} catch (error) {
console.log(error.name); // URIError
}decodeURIComponent очікує правильно закодований компонент URI. Символ % без наступних шістнадцяткових цифр є некоректним кодуванням.
EvalErrorEvalError пов’язаний із функцією eval. У сучасному JavaScript він практично не виникає автоматично.
throw new EvalError("Помилка виконання коду");Для звичайних програм цей тип майже не використовують. Функцію eval також зазвичай уникають через складність аналізу та ризики безпеки.
AggregateErrorAggregateError описує кілька помилок одночасно. Він може виникнути, наприклад, коли кілька промісів відхилилися під час Promise.any.
Помилки доступні у властивості errors:
const error = new AggregateError(
[
new Error("Сервер недоступний"),
new Error("Перевищено час очікування")
],
"Усі спроби завершилися невдало"
);
console.log(error.name); // AggregateError
console.log(error.message); // Усі спроби завершилися невдало
console.log(error.errors); // Масив початкових помилокДля перевірки типу помилки використовують оператор instanceof.
try {
const value = null;
value.toUpperCase();
} catch (error) {
if (error instanceof TypeError) {
console.log("Операція виконана над значенням неправильного типу");
}
}Оскільки спеціалізовані помилки успадковують властивості Error, можна перевіряти також базовий тип:
const error = new RangeError("Неприпустиме значення");
console.log(error instanceof RangeError); // true
console.log(error instanceof Error); // trueПеревірка instanceof Error підходить, коли потрібно обробити будь-яку стандартну помилку. Перевірка конкретного підтипу дає змогу виконати точнішу обробку.
Іноді обробник може виконати частину роботи, але не може повністю обробити помилку. У такому разі помилку можна викинути повторно.
function readUser(user) {
try {
return user.name.toUpperCase();
} catch (error) {
console.log("Не вдалося прочитати ім’я користувача");
throw error;
}
}
try {
readUser(null);
} catch (error) {
console.log("Помилку перехоплено у зовнішньому коді");
console.log(error.name);
}Не варто без потреби замінювати оригінальну помилку новою, адже можна втратити корисний контекст і стек викликів.
Розглянемо функцію, яка перевіряє дані користувача:
function createUser(name, age) {
if (typeof name !== "string") {
throw new TypeError("Ім’я має бути рядком");
}
if (name.trim() === "") {
throw new Error("Ім’я не може бути порожнім");
}
if (!Number.isInteger(age)) {
throw new TypeError("Вік має бути цілим числом");
}
if (age < 0 || age > 120) {
throw new RangeError("Вік має бути від 0 до 120 років");
}
return {
name: name.trim(),
age
};
}
try {
const user = createUser("Олена", 25);
console.log("Користувача створено:", user);
} catch (error) {
if (error instanceof TypeError) {
console.log("Помилка типу даних:", error.message);
} else if (error instanceof RangeError) {
console.log("Помилка діапазону:", error.message);
} else if (error instanceof Error) {
console.log("Помилка:", error.message);
}
}У цьому прикладі:
TypeError використовується для неправильного типу значення.
RangeError використовується для числа поза допустимим діапазоном.
Загальний Error використовується для порожнього імені.
instanceof допомагає вибрати спосіб обробки помилки.
За потреби можна створити власний клас помилки на основі Error.
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
try {
throw new ValidationError("Поле email є обов’язковим");
} catch (error) {
console.log(error.name); // ValidationError
console.log(error.message); // Поле email є обов’язковим
}Власні класи корисні у великих програмах, коли потрібно відрізняти помилки різних частин застосунку.
Такий об’єкт також є екземпляром Error:
const error = new ValidationError("Некоректні дані");
console.log(error instanceof ValidationError); // true
console.log(error instanceof Error); // trueErrorНе рекомендовано:
throw "Помилка";Краще:
throw new Error("Помилка");Об’єкт Error має name, message і стек викликів.
Не варто визначати тип помилки за її текстом:
if (error.message === "Щось пішло не так") {
// Такий підхід ненадійний
}Текст повідомлення може змінитися. Краще перевіряти тип:
if (error instanceof TypeError) {
// Обробка помилки типу
}Порожній catch приховує проблему:
try {
performOperation();
} catch (error) {
// Помилка повністю проігнорована
}Якщо помилку неможливо обробити, її варто записати в журнал або передати далі:
try {
performOperation();
} catch (error) {
console.error(error);
throw error;
}throw і returnreturn повертає значення з функції, а throw перериває звичайне виконання та передає помилку обробнику.
function getValue() {
return "Значення";
}
function fail() {
throw new Error("Операція не вдалася");
}error поза блоком catchЗмінна помилки доступна лише всередині відповідного блоку catch:
try {
throw new Error("Помилка");
} catch (error) {
console.log(error.message);
}
// Тут error недоступнаError — стандартний об’єкт для опису помилок у JavaScript.
Основні властивості помилки — name, message і stack.
Оператор throw викидає помилку.
Конструкція try...catch перехоплює та обробляє помилки.
finally виконується незалежно від того, чи виникла помилка.
TypeError означає неправильний тип або неможливу для типу операцію.
ReferenceError виникає під час звернення до невідомої змінної.
SyntaxError означає неправильний синтаксис.
RangeError вказує на значення поза допустимим діапазоном.
URIError пов’язаний із некоректними URI.
AggregateError може містити кілька помилок.
Для перевірки типу помилки використовують instanceof.
У більшості випадків краще викидати Error або його підтипи, а не рядки чи інші довільні значення.