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

Как отлавливать исключения в Promise?

2.0 Middle🔥 241 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Обработка исключений в Promise

Обработка ошибок в Promise - критически важная часть асинхронного программирования на JavaScript/TypeScript. Существует несколько способов отловить и обработать исключения.

Метод .catch()

Это самый простой и классический способ обработки ошибок в Promise цепочке:

fetch('/api/users')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    console.error('Ошибка при загрузке:', error);
  });

Метод .catch() перехватывает любую ошибку из цепочки Promise - как из rejected промиса, так и из выброшенного исключения в .then() блоках.

Async/Await с try/catch

Современный и более читаемый подход с использованием async/await:

async function fetchUsers() {
  try {
    const response = await fetch('/api/users');
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Ошибка:', error);
    // Перебросить или обработать
    throw error;
  } finally {
    console.log('Загрузка завершена');
  }
}

Обработка разных типов ошибок

async function processData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
  } catch (error) {
    if (error instanceof TypeError) {
      console.error('Ошибка сети:', error);
    } else if (error instanceof SyntaxError) {
      console.error('Ошибка парсинга JSON:', error);
    } else {
      console.error('Неизвестная ошибка:', error);
    }
  }
}

Promise.all() с обработкой ошибок

// Вариант 1: любая ошибка отменяет всё
Promise.all([promise1, promise2, promise3])
  .then(results => console.log('Успех:', results))
  .catch(error => console.error('Одна из ошибок:', error));

// Вариант 2: обрабатываем каждую ошибку отдельно
Promise.allSettled([promise1, promise2, promise3])
  .then(results => {
    results.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        console.log(`Promise ${index} успешен:`, result.value);
      } else {
        console.error(`Promise ${index} ошибка:`, result.reason);
      }
    });
  });

Обработка ошибок с повторными попытками

async function fetchWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      return await response.json();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      console.log(`Попытка ${i + 1} не удалась, повторяю...`);
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

Custom Error классы

class APIError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name = 'APIError';
    this.statusCode = statusCode;
  }
}

async function fetchData() {
  try {
    const response = await fetch('/api/data');
    if (!response.ok) {
      throw new APIError(
        `Ошибка сервера: ${response.statusText}`,
        response.status
      );
    }
    return await response.json();
  } catch (error) {
    if (error instanceof APIError) {
      console.error(`API Ошибка [${error.statusCode}]:`, error.message);
    } else {
      console.error('Системная ошибка:', error);
    }
  }
}

Лучшие практики

1. Всегда обрабатывай ошибки - неуловленное отклонение Promise вызывает unhandledrejection событие:

window.addEventListener('unhandledrejection', event => {
  console.error('Необработанная ошибка Promise:', event.reason);
});

2. Не оставляй catch пустым:

// Плохо
fetch('/api').catch(() => {});

// Хорошо
fetch('/api').catch(error => {
  console.error('Ошибка загрузки:', error);
  // Показать пользователю или логировать
});

3. Различай HTTP ошибки и сетевые ошибки:

async function safeFetch(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
    return response;
  } catch (error) {
    if (error instanceof TypeError) {
      // Сетевая ошибка
      console.error('Нет соединения');
    } else {
      // HTTP ошибка
      console.error(error.message);
    }
    throw error;
  }
}

Правильная обработка ошибок в Promise делает приложение более надёжным и улучшает пользовательский опыт.