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

Что в Promise выполняется синхронно?

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

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

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

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

Что в Promise выполняется синхронно?

В Promise синхронно выполняется функция-конструктор (executor), которую вы передаёте при создании. Всё остальное (.then(), .catch(), .finally()) выполняется асинхронно в микротасках.

Синхронное выполнение: код в конструкторе

console.log('1. До создания Promise');

const promise = new Promise((resolve, reject) => {
  console.log('2. Код внутри Promise выполняется СИНХРОННО');
  resolve('успех');
  console.log('3. Можно выполнять код ДО resolve');
});

console.log('4. После создания Promise');
console.log('5. Добавляю .then()');

promise.then((result) => {
  console.log('6. .then() выполнится АСИНХРОННО:', result);
});

console.log('7. Конец синхронного кода');

Вывод:

1. До создания Promise
2. Код внутри Promise выполняется СИНХРОННО
3. Можно выполнять код ДО resolve
4. После создания Promise
5. Добавляю .then()
7. Конец синхронного кода
6. .then() выполнится АСИНХРОННО: успех

Почему это важно: отката исключений

const promise = new Promise((resolve, reject) => {
  console.log('Начало');
  throw new Error('Ошибка в конструкторе');
  console.log('Это не выполнится');
});

// Ошибка поймана автоматически и преобразована в rejected promise
promise.catch((error) => {
  console.log('Поймали ошибку:', error.message);
});

Ошибка в конструкторе автоматически переводит Promise в rejected состояние. Это работает потому, что код выполняется синхронно.

Асинхронное выполнение: handlers (.then, .catch, .finally)

const promise = Promise.resolve('данные');

console.log('1. До .then()');

promise
  .then((result) => {
    console.log('2. .then() выполнится АСИНХРОННО:', result);
    return result.toUpperCase();
  })
  .then((upper) => {
    console.log('3. Второй .then():', upper);
  })
  .catch((error) => {
    console.log('4. .catch() если ошибка');
  })
  .finally(() => {
    console.log('5. .finally() выполнится в конце');
  });

console.log('6. Конец синхронного кода');

Вывод:

1. До .then()
6. Конец синхронного кода
2. .then() выполнится АСИНХРОННО: данные
3. Второй .then(): ДАННЫЕ
5. .finally() выполнится в конце

Все handlers выполняются ПОСЛЕ завершения синхронного кода (в микротасках).

Порядок исполнения: микротаски vs макротаски

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

Promise.resolve()
  .then(() => console.log('2. Микротаска (Promise)'));

setTimeout(() => {
  console.log('3. Макротаска (setTimeout)');
}, 0);

console.log('4. Ещё синхронный код');

Вывод:

1. Синхронный код
4. Ещё синхронный код
2. Микротаска (Promise)
3. Макротаска (setTimeout)

Порядок: синхронный код -> микротаски -> макротаски

Практический пример: инициализация приложения

class ApiClient {
  constructor(baseUrl) {
    // СИНХРОННО: инициализируем свойства
    this.baseUrl = baseUrl;
    this.isReady = false;
    console.log('ApiClient создан (синхронно)');
  }

  async init() {
    // АСИНХРОННО: загружаем конфиг
    try {
      const config = await fetch(`${this.baseUrl}/config`).then(r => r.json());
      this.isReady = true;
      console.log('ApiClient готов (асинхронно)');
      return config;
    } catch (error) {
      console.error('Ошибка инициализации');
    }
  }
}

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

const client = new ApiClient('https://api.example.com');
console.log('2. client.isReady:', client.isReady); // false - конструктор синхронный

client.init().then(() => {
  console.log('3. client.isReady:', client.isReady); // true - init асинхронный
});

console.log('4. Конец синхронного кода');

Вывод:

1. Начало
ApiClient создан (синхронно)
2. client.isReady: false
4. Конец синхронного кода
ApiClient готов (асинхронно)
3. client.isReady: true

Частая ошибка: забывают о синхронности конструктора

// ОШИБКА: код выполнится НЕ в том порядке, что вы ожидаете
new Promise((resolve) => {
  setTimeout(() => {
    console.log('1. setTimeout в конструкторе');
    resolve('готово');
  }, 0);
}).then(() => {
  console.log('2. .then()');
});

console.log('3. Синхронный код');

Вывод:

3. Синхронный код
1. setTimeout в конструкторе
2. .then()

setTimeout внутри конструктора — это МАКРОТАСКА, поэтому выполнится ПОСЛЕ микротасок (Promise.then).

Ключевые выводы

  • Конструктор Promise (executor) выполняется синхронно
  • Все handlers (.then, .catch, .finally) выполняются асинхронно в микротасках
  • Ошибки в конструкторе автоматически переводят Promise в rejected
  • Порядок: синхронный код -> микротаски -> макротаски
  • Важно помнить при оптимизации и отладке асинхронного кода

Это фундаментальное понимание браузерного event loop необходимо каждому JavaScript разработчику.

Что в Promise выполняется синхронно? | PrepBro