Пошук уроків, статей та іншого контенту
Навчитеся перехоплювати помилки за допомогою конструкції try...catch і безпечно виконувати код, який може завершитися помилкою.
Під час виконання програми можуть виникати помилки:
користувач увів некоректні дані;
файл або ресурс недоступний;
рядок має неправильний формат;
викликається метод, якого не існує;
програма отримала неочікуване значення.
Якщо помилку не обробити, виконання JavaScript-коду може зупинитися. Конструкція try...catch дає змогу спробувати виконати небезпечний код і перехопити помилку, якщо вона виникне.
try...catchtry {
// Код, під час виконання якого може виникнути помилка
} catch (error) {
// Код, який виконається, якщо виникла помилка
}Блок try містить код, який ми перевіряємо. Якщо під час його виконання виникає помилка, JavaScript:
припиняє виконання блоку try;
передає помилку в блок catch;
продовжує виконання програми після catch.
try {
console.log(userName);
} catch (error) {
console.log("Сталася помилка під час читання змінної");
}
console.log("Програма продовжує виконання");Змінна userName не оголошена, тому в блоці try виникає помилка ReferenceError. Блок catch перехоплює її, і програма не завершується аварійно.
Результат:
Сталася помилка під час читання змінної
Програма продовжує виконанняПараметр error у блоці catch містить інформацію про помилку. Найчастіше використовують такі властивості:
error.name — назва типу помилки;
error.message — повідомлення про помилку;
error.stack — стек викликів, корисний під час налагодження.
try {
const number = JSON.parse("це не JSON");
console.log(number);
} catch (error) {
console.log("Назва:", error.name);
console.log("Повідомлення:", error.message);
}Можливий результат:
Назва: SyntaxError
Повідомлення: Unexpected token ...Назва та точний текст повідомлення можуть відрізнятися залежно від середовища виконання JavaScript.
Назва error не є спеціальним словом. Параметр можна назвати інакше:
try {
JSON.parse("неправильний рядок");
} catch (exception) {
console.log(exception.message);
}Проте назва error є найпоширенішою і зрозумілою.
У сучасному JavaScript параметр можна не вказувати, якщо інформація про помилку не потрібна:
try {
JSON.parse("неправильний рядок");
} catch {
console.log("Рядок має неправильний формат");
}Метод JSON.parse() перетворює JSON-рядок на JavaScript-значення. Якщо рядок має неправильний формат, метод генерує помилку.
function parseUser(json) {
try {
const user = JSON.parse(json);
console.log(`Користувач: ${user.name}`);
return user;
} catch (error) {
console.log("Не вдалося прочитати дані користувача");
console.log(`Причина: ${error.message}`);
return null;
}
}
const validJson = '{"name":"Олена","age":28}';
const invalidJson = '{"name":"Олена",}';
const firstUser = parseUser(validJson);
const secondUser = parseUser(invalidJson);
console.log(firstUser);
console.log(secondUser);Для правильного JSON функція поверне об’єкт. Для неправильного — виведе повідомлення і поверне null.
Перехоплення помилки не означає, що дані автоматично стали правильними. Програма має вирішити, що робити далі:
повернути значення за замовчуванням;
показати повідомлення користувачу;
записати інформацію в журнал;
повторити операцію;
повернути null або інший спеціальний результат.
finallyКонструкція може мати третій блок — finally:
try {
// Код, який може завершитися помилкою
} catch (error) {
// Обробка помилки
} finally {
// Код, який виконається в будь-якому випадку
}Блок finally виконується:
якщо помилка не виникла;
якщо помилка виникла і була перехоплена;
навіть якщо в блоці try або catch використано return.
Його використовують для завершальних дій: очищення ресурсів, приховування індикатора завантаження або закриття з’єднання.
function readData() {
console.log("Початок читання даних");
try {
const data = JSON.parse('{"status":"ok"}');
console.log(data.status);
} catch (error) {
console.log("Не вдалося прочитати дані");
} finally {
console.log("Операцію завершено");
}
}
readData();Результат:
Початок читання даних
ok
Операцію завершеноНавіть якщо замінити JSON на неправильний, повідомлення Операцію завершено все одно буде виведено.
throwJavaScript дає змогу створювати помилки самостійно за допомогою throw. Це корисно, коли значення технічно правильне, але не відповідає правилам програми.
function checkAge(age) {
if (typeof age !== "number") {
throw new TypeError("Вік має бути числом");
}
if (age < 0) {
throw new RangeError("Вік не може бути від’ємним");
}
return `Вік прийнято: ${age}`;
}
try {
console.log(checkAge(-3));
} catch (error) {
console.log(`${error.name}: ${error.message}`);
}Тут функція сама генерує помилку RangeError, якщо вік від’ємний.
Найчастіше для власних помилок використовують:
new Error(...) — загальна помилка;
new TypeError(...) — неправильний тип значення;
new RangeError(...) — значення поза допустимим діапазоном.
try...catchtry...catch доречний, коли помилка є очікуваною або програмі потрібно коректно відреагувати на неї.
Наприклад:
оброблення даних із зовнішнього джерела;
розбір JSON;
робота з API та файлами;
перевірка значень у функціях;
виконання операції, яка може не вдатися.
Не варто обгортати весь код програми в один великий блок try. Краще розміщувати в ньому лише операції, які справді можуть спричинити помилку.
try...catch і асинхронний кодЗвичайний try...catch перехоплює синхронні помилки. Для асинхронного коду з async і await його можна використовувати так:
async function loadData() {
try {
const response = await fetch("https://example.com/data.json");
if (!response.ok) {
throw new Error(`Помилка HTTP: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.log("Не вдалося завантажити дані");
console.log(error.message);
}
}
loadData();У цьому прикладі try...catch перехоплює помилки, пов’язані з await.
Для промісів без await зазвичай використовують .catch():
fetch("https://example.com/data.json")
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log("Не вдалося отримати дані");
console.log(error.message);
});try {
importantOperation();
} catch {
// Нічого не робимо
}Такий код приховує помилку, але не виправляє її. Пізніше буде складно зрозуміти, чому програма працює неправильно.
Краще хоча б повідомити про проблему:
try {
importantOperation();
} catch (error) {
console.error("Помилка під час виконання операції:", error);
}try занадто багато кодуtry {
const user = getUser();
validateUser(user);
saveUser(user);
sendNotification(user);
} catch (error) {
console.log("Щось пішло не так");
}У такому випадку незрозуміло, яка саме операція завершилася помилкою. Краще обмежувати блок try потрібною ділянкою або додавати точніші повідомлення.
try...catch перевірить логічні помилкиtry {
const age = -10;
console.log(age);
} catch {
console.log("Помилка");
}Цей код не спричиняє винятку, хоча від’ємний вік може бути некоректним для програми. try...catch не перевіряє бізнес-правила автоматично. Для цього потрібні власні умови та throw.
try...catch замість перевіркиЯкщо ситуацію можна легко перевірити умовою, часто краще використати if:
const number = 10;
if (typeof number === "number") {
console.log(number * 2);
} else {
console.log("Потрібно ввести число");
}try...catch призначений насамперед для оброблення виняткових ситуацій, а не для кожної звичайної перевірки.
Створіть функцію parseNumber, яка:
отримує рядок;
намагається перетворити його за допомогою JSON.parse;
повертає число, якщо результат має тип number;
у разі помилки або неправильного типу повертає null.
Один із можливих варіантів:
function parseNumber(value) {
try {
const result = JSON.parse(value);
if (typeof result !== "number") {
throw new TypeError("Значення не є числом");
}
return result;
} catch (error) {
console.log(`Не вдалося отримати число: ${error.message}`);
return null;
}
}
console.log(parseNumber("42"));
console.log(parseNumber('"42"'));
console.log(parseNumber("abc"));try містить код, який може спричинити помилку.
catch перехоплює помилку та дає змогу обробити її.
Об’єкт помилки зазвичай містить name і message.
finally виконується після try та catch у будь-якому випадку.
throw дає змогу генерувати власні помилки.
try...catch не замінює звичайні перевірки через if.
Асинхронні помилки можна обробляти через try...catch разом із await або через .catch().
Не слід мовчки ігнорувати помилки — програма має повідомити про них або коректно відновити роботу.