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

Что будет если в функции executor в Promise затронуть exception?

1.3 Junior🔥 283 комментариев
#JavaScript Core

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

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

Когда в функции executor промиса возникает необработанное исключение (exception), промис автоматически переходит в состояние rejected. Это фундаментальное поведение промисов в JavaScript, которое обеспечивает предсказуемую обработку ошибок в асинхронном коде.

Механизм работы

Функция executor выполняется синхронно сразу при создании промиса. Конструктор Promise внутренне оборачивает выполнение executor в try-catch блок:

// Пример того, что происходит "под капотом"
class Promise {
  constructor(executor) {
    // Внутренняя реализация примерно такая:
    try {
      executor(
        (value) => { /* resolve логика */ },
        (reason) => { /* reject логика */ }
      );
    } catch (error) {
      // Пойманное исключение автоматически отклоняет промис
      this.reject(error);
    }
  }
}

Практический пример

const promise = new Promise((resolve, reject) => {
  // Синхронное исключение в executor
  throw new Error('Что-то пошло не так!');
  
  // Этот код никогда не выполнится
  resolve('Успех');
});

// Обработка через catch
promise
  .then(result => {
    console.log('Успех:', result);
  })
  .catch(error => {
    console.error('Ошибка:', error.message); // Ошибка: Что-то пошло не так!
  });

// Или через второй параметр then
promise.then(
  result => console.log('Успех:', result),
  error => console.error('Ошибка:', error.message)
);

Ключевые особенности поведения

Автоматический переход в rejected:

  • Любое необработанное исключение в executor приводит к reject
  • Это происходит даже если исключение выброшено асинхронно (через setTimeout)
const asyncErrorPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    throw new Error('Асинхронная ошибка!');
  }, 0);
});

// Этот промис НЕ будет обработан через catch!
// Исключение будет непойманным (uncaught), так как происходит
// уже после того как executor завершил выполнение

Разница между throw и reject():

  • throw error и reject(error) приводят к одинаковому результату
  • Но throw обеспечивает более лаконичный синтаксис
// Эти два промиса ведут себя идентично
const p1 = new Promise((resolve, reject) => {
  throw new Error('Ошибка 1');
});

const p2 = new Promise((resolve, reject) => {
  reject(new Error('Ошибка 2'));
});

Важные нюансы и лучшие практики

Необработанные исключения:

  • Если промис с исключением в executor не имеет обработчика .catch(), ошибка станет "unhandled promise rejection"
  • В Node.js это может завершить процесс, если не настроен обработчик
// Опасный код - unhandled promise rejection
new Promise((resolve, reject) => {
  throw new Error('Непойманная ошибка!');
});
// В консоли: UnhandledPromiseRejectionWarning

Рекомендации по обработке:

  1. Всегда добавляйте обработку ошибок:
promise
  .then(handleSuccess)
  .catch(handleError); // Обязательная обработка
  1. Используйте async/await с try-catch:
async function fetchData() {
  try {
    const data = await new Promise((resolve, reject) => {
      // Код, который может выбросить исключение
      throw new Error('Ошибка в промиссе');
    });
    return data;
  } catch (error) {
    console.error('Поймано в async функции:', error);
    throw error; // Проброс дальше при необходимости
  }
}
  1. Глобальная обработка неотловленных промисов:
// В Node.js
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

// В браузере
window.addEventListener('unhandledrejection', event => {
  console.error('Unhandled rejection:', event.reason);
  event.preventDefault(); // Предотвратить вывод в консоль по умолчанию
});

Итог

Исключение в функции executor промиса — это штатный способ отклонения промиса, а не катастрофическая ошибка. Механизм автоматического преобразования исключений в reject обеспечивает:

  • Единый интерфейс обработки синхронных и асинхронных ошибок
  • Предсказуемое поведение промисов
  • Возможность цепочки обработки через .catch()

Главное — всегда предусматривать обработку возможных ошибок через .catch() или глобальные обработчики, чтобы избежать непредсказуемого поведения приложения.