Try…catch — это конструкция в JavaScript для обработки ошибок, которая позволяет перехватывать и обрабатывать исключения, возникающие во время выполнения кода. Блок try содержит код, который может вызвать ошибку, а блок catch — код для обработки этой ошибки. Опциональный блок finally выполняется в любом случае, независимо от того, возникла ошибка или нет.
Основные преимущества:
Try…catch — это фундаментальная конструкция обработки ошибок в JavaScript, которая позволяет грациозно обрабатывать исключения и предотвращать аварийное завершение программы. Это особенно важно в асинхронном коде и при работе с внешними API.
Конструкция try…catch состоит из трех частей:
try {
// Код, который может вызвать ошибку
const result = riskyOperation();
console.log(result);
} catch (error) {
// Обработка ошибки
console.error('Произошла ошибка:', error.message);
} finally {
// Опциональный блок, выполняющийся в любом случае
console.log('Очистка ресурсов');
}Часто используется при парсинге JSON данных:
function parseUserData(jsonString) {
try {
const userData = JSON.parse(jsonString);
return userData;
} catch (error) {
if (error instanceof SyntaxError) {
console.error('Некорректный формат JSON:', error.message);
return null;
} else {
throw error; // Перебрасываем другие типы ошибок
}
}
}
// Использование
const validJson = '{"name": "Иван", "age": 30}';
const invalidJson = '{"name": "Иван", "age":}'; // Некорректный JSON
console.log(parseUserData(validJson)); // {name: "Иван", age: 30}
console.log(parseUserData(invalidJson)); // null (с сообщением об ошибке)Важно при выполнении HTTP-запросов:
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP ошибка: ${response.status}`);
}
const userData = await response.json();
return userData;
} catch (error) {
if (error instanceof TypeError) {
console.error('Ошибка сети:', error.message);
} else if (error.message.includes('HTTP ошибка')) {
console.error('Ошибка сервера:', error.message);
} else {
console.error('Неизвестная ошибка:', error.message);
}
// Возвращаем значение по умолчанию
return { id: userId, name: 'Пользователь не найден' };
}
}Полезно при работе с браузерным хранилищем:
function saveToLocalStorage(key, data) {
try {
localStorage.setItem(key, JSON.stringify(data));
console.log('Данные успешно сохранены');
} catch (error) {
if (error instanceof DOMException) {
if (error.name === 'QuotaExceededError') {
console.error('Превышена квота хранилища');
} else {
console.error('Ошибка доступа к хранилищу:', error.message);
}
} else {
console.error('Неизвестная ошибка:', error.message);
}
}
}
function loadFromLocalStorage(key) {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch (error) {
console.error('Ошибка загрузки данных:', error.message);
return null;
}
}function validateUserInput(input) {
try {
// Проверка обязательных полей
if (!input.name || !input.email) {
throw new Error('Обязательные поля не заполнены');
}
// Проверка формата email
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(input.email)) {
throw new Error('Некорректный формат email');
}
// Проверка возраста
if (input.age && (input.age < 0 || input.age > 150)) {
throw new Error('Некорректный возраст');
}
return { isValid: true, data: input };
} catch (error) {
return { isValid: false, error: error.message };
}
}
// Использование
const validInput = { name: 'Иван', email: 'ivan@example.com', age: 25 };
const invalidInput = { name: 'Иван', email: 'invalid-email' };
console.log(validateUserInput(validInput)); // { isValid: true, ... }
console.log(validateUserInput(invalidInput)); // { isValid: false, error: "Некорректный формат email" }async function processMultipleOperations() {
const operations = [
fetch('/api/data1'),
fetch('/api/data2'),
fetch('/api/data3')
];
try {
// Выполняем все операции параллельно
const results = await Promise.all(operations.map(op =>
op.catch(error => ({ error }))
));
// Обрабатываем результаты
const successful = results.filter(result => !result.error);
const failed = results.filter(result => result.error);
console.log(`Успешно: ${successful.length}, Ошибок: ${failed.length}`);
return { successful, failed };
} catch (error) {
console.error('Критическая ошибка:', error.message);
throw error;
}
}// Кастомный класс ошибки
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
function processFormData(formData) {
try {
// Валидация
if (!formData.username) {
throw new ValidationError('Имя пользователя обязательно', 'username');
}
if (formData.username.length < 3) {
throw new ValidationError('Имя пользователя должно быть не менее 3 символов', 'username');
}
if (!formData.password) {
throw new ValidationError('Пароль обязателен', 'password');
}
// Обработка данных
return { success: true, data: formData };
} catch (error) {
if (error instanceof ValidationError) {
return {
success: false,
error: error.message,
field: error.field
};
} else {
// Другие типы ошибок
return {
success: false,
error: 'Произошла неизвестная ошибка'
};
}
}
}// ❌ Игнорирование ошибок
try {
riskyOperation();
} catch (error) {
// Пустой блок catch - плохая практика
}
// ✅ Правильная обработка
try {
riskyOperation();
} catch (error) {
console.error('Ошибка:', error.message);
// Или отправка в систему логирования
logError(error);
}// ❌ Перехват всех ошибок одинаково
try {
riskyOperation();
} catch (error) {
alert('Произошла ошибка'); // Неинформативно
}
// ✅ Различная обработка разных типов ошибок
try {
riskyOperation();
} catch (error) {
if (error instanceof TypeError) {
console.error('Ошибка типа:', error.message);
} else if (error instanceof ReferenceError) {
console.error('Ошибка ссылки:', error.message);
} else {
console.error('Другая ошибка:', error.message);
}
}// ❌ Забытый finally для очистки ресурсов
function processFile(filename) {
let file;
try {
file = openFile(filename);
return processData(file);
} catch (error) {
console.error('Ошибка обработки файла:', error);
}
// Файл может остаться открытым!
}
// ✅ Правильное использование finally
function processFile(filename) {
let file;
try {
file = openFile(filename);
return processData(file);
} catch (error) {
console.error('Ошибка обработки файла:', error);
throw error;
} finally {
// Всегда закрываем файл
if (file) {
closeFile(file);
}
}
}| Метод | Преимущества | Недостатки |
|---|---|---|
| try…catch | Гибкий, понятный синтаксис | Может скрывать ошибки |
| Promise.catch() | Для асинхронных операций | Цепочки могут быть сложными |
| window.onerror | Глобальная обработка | Только для ошибок выполнения |
| process.on(‘uncaughtException’) | Для Node.js | Только для необработанных ошибок |
Try…catch — это важный инструмент для создания надежных JavaScript-приложений. Понимание правильного использования этой конструкции помогает создавать более стабильный и предсказуемый код.
Что будет выведено в консоль и почему? Исправьте код, если необходимо:
function divide(a, b) {
if (b === 0) {
throw new Error('Деление на ноль');
}
return a / b;
}
function calculate() {
try {
console.log('1. Начало расчета');
const result1 = divide(10, 2);
console.log('2. Результат 1:', result1);
const result2 = divide(10, 0);
console.log('3. Результат 2:', result2);
const result3 = divide(20, 4);
console.log('4. Результат 3:', result3);
} catch (error) {
console.log('5. Ошибка:', error.message);
}
console.log('6. Конец расчета');
}
calculate();Ответ: Будет выведено в консоль:
1. Начало расчета
2. Результат 1: 5
5. Ошибка: Деление на ноль
6. Конец расчета
Объяснение:
console.log('1. Начало расчета')divide(10, 2) — возвращает 5, выводится “2. Результат 1: 5”divide(10, 0) — выбрасывается исключение Error(‘Деление на ноль’)Исправленная версия с обработкой каждой операции отдельно:
function divide(a, b) {
if (b === 0) {
throw new Error('Деление на ноль');
}
return a / b;
}
function calculate() {
console.log('1. Начало расчета');
// Обработка каждой операции отдельно
try {
const result1 = divide(10, 2);
console.log('2. Результат 1:', result1);
} catch (error) {
console.log('Ошибка в операции 1:', error.message);
}
try {
const result2 = divide(10, 0);
console.log('3. Результат 2:', result2);
} catch (error) {
console.log('Ошибка в операции 2:', error.message);
}
try {
const result3 = divide(20, 4);
console.log('4. Результат 3:', result3);
} catch (error) {
console.log('Ошибка в операции 3:', error.message);
}
console.log('5. Конец расчета');
}
calculate();Это выведет:
1. Начало расчета
2. Результат 1: 5
Ошибка в операции 2: Деление на ноль
4. Результат 3: 5
5. Конец расчета
Важно понимать, что при возникновении исключения в блоке try, выполнение немедленно переходит в блок catch, и остальной код в блоке try не выполняется.
Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪