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

Функция executor в Promise выполняется синхронно или асинхронно

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

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

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

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

Функция executor в Promise: синхронное выполнение с асинхронными последствиями

Функция executor в Promise всегда выполняется СИНХРОННО и НЕМЕДЛЕННО в момент создания промиса. Это фундаментальное поведение, которое важно понять для правильной работы с асинхронным кодом в JavaScript.

Синхронная природа executor

Когда вы создаете промис, функция executor выполняется моментально:

console.log('До создания промиса');

const promise = new Promise((resolve, reject) => {
  console.log('Executor выполняется'); // Синхронно!
  resolve('Результат');
});

console.log('После создания промиса');

// Вывод:
// До создания промиса
// Executor выполняется
// После создания промиса

Ключевой момент: executor запускается в той же микротаске, в которой создается промис. Это синхронная операция.

Разделение синхронного executor и асинхронных обработчиков

Хотя executor выполняется синхронно, обработчики промисов (then, catch, finally) всегда вызываются асинхронно, даже если промис уже разрешен:

console.log('1. Синхронный код до промиса');

const promise = new Promise((resolve) => {
  console.log('2. Executor выполняется синхронно');
  resolve('Успех!');
  console.log('3. Код после resolve, но до обработчиков');
});

promise.then((result) => {
  console.log('5. Обработчик then (выполняется асинхронно)');
});

console.log('4. Синхронный код после промиса');

// Вывод:
// 1. Синхронный код до промиса
// 2. Executor выполняется синхронно
// 3. Код после resolve, но до обработчиков
// 4. Синхронный код после промиса
// 5. Обработчик then (выполняется асинхронно)

Последствия для асинхронных операций

На практике executor часто содержит асинхронные операции, но сама функция executor и ее начальное выполнение остаются синхронными:

console.log('Начало');

const asyncPromise = new Promise((resolve, reject) => {
  console.log('Executor начал выполнение синхронно');
  
  // Асинхронная операция внутри executor
  setTimeout(() => {
    console.log('Таймаут завершен');
    resolve('Асинхронный результат');
  }, 1000);
  
  console.log('Executor закончил синхронную часть');
});

console.log('Синхронный код продолжается');

Почему это важно: практические аспекты

  1. Ошибки в executor обрабатываются синхронно:

    try {
      const promise = new Promise(() => {
        throw new Error('Ошибка в executor');
      });
    } catch (error) {
      console.log('Ошибка перехвачена:', error.message);
    }
    
  2. Синхронный resolve не означает синхронный then:

    const promise = Promise.resolve('Немедленное значение');
    
    promise.then(value => {
      console.log(value); // Выполнится асинхронно
    });
    
    console.log('Это выведется первым');
    
  3. Исключения в executor автоматически преобразуются в отклоненные промисы:

    const faultyPromise = new Promise(() => {
      throw new Error('Автоматический reject');
    });
    
    faultyPromise.catch(error => {
      console.log('Поймана ошибка:', error.message); // Асинхронно
    });
    

Отличия Promise.resolve() от new Promise()

Интересный нюанс: Promise.resolve() создает уже разрешенный промис без выполнения executor, но обработчики все равно вызываются асинхронно:

const immediate = Promise.resolve('Готово');

immediate.then(() => {
  console.log('Это все равно асинхронно');
});

console.log('Это выведется первым');

Микротаски и очередь событий

Обработчики промисов (then/catch/finally) помещаются в очередь микротаск, которая обрабатывается после текущего синхронного кода, но до макротаск (таких как setTimeout):

console.log('Старт');

setTimeout(() => console.log('setTimeout'), 0);

Promise.resolve()
  .then(() => console.log('Promise.then 1'))
  .then(() => console.log('Promise.then 2'));

console.log('Конец');

// Вывод:
// Старт
// Конец
// Promise.then 1
// Promise.then 2
// setTimeout

Вывод: Функция executor промиса всегда выполняется синхронно в момент создания промиса, что позволяет инициализировать асинхронные операции немедленно. Однако все обработчики промисов (then, catch, finally) выполняются асинхронно через очередь микротаск, обеспечивая предсказуемый порядок выполнения и предотвращая блокировку основного потока. Это разделение — основа неблокирующей асинхронной модели JavaScript.