← Назад к вопросам

Можно ли выполнять 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 работал корректно. Это делает асинхронный код похожим на синхронный и упрощает обработку ошибок.

Можно ли выполнять try-catch-finally в синхронном коде? | PrepBro