← Назад к вопросам
Можно ли выполнять try-catch-finally в синхронном коде?
2.3 Middle🔥 181 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Try-Catch-Finally в синхронном коде
Да, полностью можно и нужно! Try-catch-finally работает в синхронном коде и это один из основных механизмов обработки ошибок в JavaScript.
Как работает try-catch-finally
Структура
try {
// Код, который может вызвать ошибку
// Если ошибка — прыгаем в catch блок
} catch (error) {
// Обработка ошибки
// Выполняется только если произошла ошибка в try
} finally {
// Выполняется ВСЕГДА
// И после успеха, и после ошибки
}
Примеры в синхронном коде
Пример 1: Обработка ошибок парсинга
const jsonString = '{invalid json}';
try {
const obj = JSON.parse(jsonString); // Вызовет ошибку
console.log('Parsed:', obj);
} catch (error) {
console.error('Failed to parse JSON:', error.message);
// Вывод: Failed to parse JSON: Unexpected token } in JSON at position 15
} finally {
console.log('Parsing attempt finished');
}
Пример 2: Работа с файлами и ресурсами
let file;
try {
file = openFile('data.txt');
const content = readFile(file);
console.log('Content:', content);
} catch (error) {
console.error('File operation failed:', error);
} finally {
// Очистка ресурсов — выполняется ВСЕГДА
if (file) {
closeFile(file);
}
}
Пример 3: Валидация данных
function validateUser(data) {
try {
if (!data.name || data.name.trim() === '') {
throw new Error('Name is required');
}
if (!data.email || !data.email.includes('@')) {
throw new Error('Invalid email');
}
if (data.age < 0 || data.age > 150) {
throw new Error('Invalid age');
}
return true;
} catch (error) {
console.error('Validation error:', error.message);
return false;
}
}
validateUser({ name: 'John' }); // Выведет ошибку про email
Разница между try-catch в синхронном и асинхронном коде
Синхронный код
// try-catch РАБОТАЕТ
try {
const result = synchronousFunction(); // Ошибка прямо здесь
console.log(result);
} catch (error) {
console.error('Error caught:', error);
}
function synchronousFunction() {
if (Math.random() > 0.5) {
throw new Error('Random error');
}
return 'Success';
}
Асинхронный код без await
// try-catch НЕ РАБОТАЕТ
try {
// Это асинхронная операция, ошибка произойдёт позже
setTimeout(() => {
throw new Error('Async error');
}, 100);
console.log('Code continues');
} catch (error) {
// Этот блок НЕ поймает ошибку из setTimeout
console.error('This will NOT be executed');
}
// Uncaught error! Ошибка выведется в консоль, не будет поймана
Асинхронный код с await
// try-catch РАБОТАЕТ с await
async function asyncFunction() {
try {
const result = await fetch('/api/data');
const data = await result.json();
console.log(data);
} catch (error) {
console.error('Error caught:', error);
}
}
// await переводит асинхронный код в синхронный стиль
Когда нужен finally блок
Очистка ресурсов
let connection;
try {
connection = openDatabaseConnection();
const data = connection.query('SELECT * FROM users');
console.log(data);
} catch (error) {
console.error('Database error:', error);
} finally {
// ВАЖНО: это выполнится в любом случае
if (connection) {
connection.close();
}
}
Логирование
try {
performCriticalOperation();
console.log('Operation succeeded');
} catch (error) {
console.error('Operation failed:', error);
} finally {
// Логирование выполнится всегда
console.log('Operation attempt completed at', new Date());
}
Возвращение значения
function getNumberWithFinally() {
try {
return 1; // Хочет вернуть 1
} finally {
console.log('Finally block'); // Выполнится ДО return
}
}
getNumberWithFinally(); // Выведет:
// Finally block
// Return value: 1
Важно: finally блок выполняется перед return!
Множественные блоки catch
Можно обрабатывать разные типы ошибок:
try {
// Код, который может вызвать ошибку
parseData();
} catch (error) {
// ES2022+ синтаксис: можно проверять тип ошибки
if (error instanceof SyntaxError) {
console.error('Syntax error:', error.message);
} else if (error instanceof TypeError) {
console.error('Type error:', error.message);
} else if (error instanceof ReferenceError) {
console.error('Reference error:', error.message);
} else {
console.error('Unknown error:', error);
}
}
Nested try-catch
try {
try {
throw new Error('Inner error');
} catch (error) {
console.error('Caught inner:', error);
throw new Error('Re-thrown as outer'); // Пробрасываем дальше
}
} catch (error) {
console.error('Caught outer:', error);
}
// Вывод:
// Caught inner: Error: Inner error
// Caught outer: Error: Re-thrown as outer
Важные правила
1. Не ловить ошибки проектирования
// ПЛОХО — ловим ошибку, которая должна быть исправлена
try {
const result = data[0].value.nested.property; // Может быть null
} catch (error) {
// Это скрывает баг!
console.log('Caught error');
}
// ХОРОШО — предотвращаем ошибку
const result = data?.[0]?.value?.nested?.property; // Optional chaining
2. Не ловить всё подряд
// ПЛОХО
try {
// Много кода
complexOperation();
moreComplexCode();
evenMoreCode();
} catch (error) {
// Откуда пришла ошибка? Невозможно понять
console.log('Something went wrong');
}
// ХОРОШО — ловим специфичные ошибки
try {
// Только операция, которая может ошибиться
const data = JSON.parse(jsonString);
} catch (error) {
console.error('Failed to parse JSON:', error);
}
3. Всегда логируй ошибки
// ПЛОХО
try {
riskyOperation();
} catch (error) {
// Молча игнорируем ошибку
}
// ХОРОШО
try {
riskyOperation();
} catch (error) {
console.error('Error details:', error);
// Также можно отправить на сервер для анализа
reportErrorToServer(error);
}
Реальные примеры
Парсинг JSON
function parseJSON(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
console.error('Invalid JSON:', error.message);
return null;
}
}
parseJSON('{"name": "John"}'); // {name: 'John'}
parseJSON('invalid'); // null
Работа с localStorage
function saveToStorage(key, value) {
try {
const serialized = JSON.stringify(value);
localStorage.setItem(key, serialized);
return true;
} catch (error) {
// localStorage может быть переполнен или отключен
console.error('Failed to save to storage:', error);
return false;
}
}
function loadFromStorage(key) {
try {
const serialized = localStorage.getItem(key);
return serialized ? JSON.parse(serialized) : null;
} catch (error) {
console.error('Failed to load from storage:', error);
return null;
}
}
Вычисления
function calculateDiscount(price, percentage) {
try {
if (typeof price !== 'number' || price < 0) {
throw new Error('Invalid price');
}
if (typeof percentage !== 'number' || percentage < 0 || percentage > 100) {
throw new Error('Invalid percentage');
}
return price * (1 - percentage / 100);
} catch (error) {
console.error('Calculation error:', error.message);
return null;
} finally {
console.log('Discount calculation completed');
}
}
Try-Catch vs Async Error Handling
// Синхронный код
try {
const result = syncOperation(); // Ошибка поймается
} catch (error) {
handleError(error);
}
// Асинхронный код — нужен await
try {
const result = await asyncOperation(); // Ошибка поймается
} catch (error) {
handleError(error);
}
// Асинхронный код БЕЗ await — ошибка НЕ поймается
try {
const result = asyncOperation(); // Это Promise
} catch (error) {
// Ошибка не произойдёт здесь
}
// Обработка Promise без await
asyncOperation()
.then(result => console.log(result))
.catch(error => handleError(error));
Вывод
Try-catch-finally полностью работает в синхронном коде и это основной механизм обработки ошибок. Ключевые моменты:
- try — код, который может ошибиться
- catch — обработка ошибки
- finally — очистка ресурсов (выполняется всегда)
Для асинхронного кода нужно использовать await, чтобы try-catch работал корректно. Это делает асинхронный код похожим на синхронный и упрощает обработку ошибок.