> В какой момент вызывается callback в конструкторе Promise в JavaScript (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: GoInvest, Яндекс
Стек: JavaScript
> Пример ответа
Короткий ответ
Callback в конструкторе Promise (executor) вызывается синхронно, немедленно при создании промиса, до того как конструктор вернет объект Promise. Это позволяет инициировать асинхронную операцию сразу. Сам callback получает два аргумента - resolve и reject, которые также являются функциями. Вызов resolve или reject может быть как синхронным, так и отложенным.
Подробное объяснение
Конструктор Promise принимает функцию-executor с сигнатурой (resolve, reject) => void. Эта функция вызывается синхронно в момент вызова new Promise(executor). Это поведение строго определено спецификацией ECMAScript: executor запускается до того, как конструктор вернет созданный объект Promise.
Это означает, что код внутри executor выполняется в текущем стеке вызовов, до возврата управления вызывающему коду. Например:
JAVASCRIPTconsole.log('before');new Promise(() => console.log('inside executor'));console.log('after');// Вывод: before, inside executor, after
При этом resolve и reject - это функции, которые также создаются синхронно и передаются в executor. Их вызов может быть как синхронным, так и асинхронным. Если resolve/reject вызываются синхронно внутри executor, промис переходит в соответствующее состояние (fulfilled/rejected) немедленно, но обработчики .then()/.catch() все равно выполняются асинхронно (в микротасках).
На практике
Синхронный вызов executor важен для:
- Немедленной валидации аргументов или инициализации
- Возможности обернуть синхронный код в промис (например,
Promise.resolve()) - Гарантии, что побочные эффекты (логирование, подписки) происходят до возврата промиса
Однако стоит избегать тяжелых синхронных операций внутри executor, так как они блокируют event loop. Типичный паттерн - инициировать асинхронную операцию (setTimeout, fetch, addEventListener) и сохранить resolve/reject для вызова позже.
Пример кода
JAVASCRIPT// Синхронный вызов executorconst promise = new Promise((resolve) => {console.log('executor start');resolve(42);console.log('executor end');});console.log('after constructor');// Вывод: executor start, executor end, after constructorpromise.then(value => console.log('then:', value));// Вывод: then: 42 (в микротаске, после синхронного кода)
Как отвечать на собеседовании
Начни с ключевого факта: executor вызывается синхронно, немедленно. Подчеркни, что это отличает его от callback в .then()/.catch(), которые всегда асинхронны. Приведи простой пример с порядком вывода. Упомяни, что resolve/reject могут вызываться как синхронно, так и асинхронно, но обработчики всегда выполняются в микротасках. Если спросят про спецификацию, упомяни, что это описано в разделе 25.6.3.1 Promise (executor).
Что проверяет интервьюер
- Понимание разницы между синхронным и асинхронным выполнением в JavaScript
- Знание event loop и очереди микротасков
- Умение предсказывать порядок выполнения кода с промисами
- Понимание внутреннего устройства конструктора Promise
Типичные ошибки
- Утверждение, что executor вызывается асинхронно (как setTimeout)
- Путаница между синхронным вызовом executor и асинхронным выполнением
.then() - Предположение, что resolve/reject внутри executor делают обработчики синхронными
- Игнорирование того, что код после resolve внутри executor все еще выполняется (executor не останавливается после вызова resolve)
> Похожие задачи по frontend
Как узнать фактически переданное количество аргументов в функцию в JavaScript
Можно ли использовать цикл for...of для перебора ключей объекта в JavaScript?
Каков порядок выполнения кода с setTimeout, Promise и цепочкой then/catch в JavaScript?
Как оптимизировать обработку кликов на ячейки большой таблицы в веб-приложении
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью