> Что сработает раньше: callback или promise (JavaScript)

Уровень: senior · Роль: frontend · Язык: JavaScript · Категория: Технические вопросы

Компании: ЭНИРАН

Стек: Node.js, JavaScript

> Пример ответа

Короткий ответ

Callback сработает раньше, чем promise. Callback выполняется синхронно в том же тике event loop, а promise (даже зарезолвленный) всегда откладывает выполнение .then() в микротаски, которые обрабатываются после завершения текущего синхронного кода, но до следующего макротаска.

Подробное объяснение

Разница в приоритете выполнения связана с тем, как JavaScript обрабатывает асинхронные операции через event loop. Callback, переданный в синхронную функцию (например, Array.prototype.forEach или fs.readFileSync), выполняется немедленно в текущем стеке вызовов. Даже в асинхронных API, таких как setTimeout с нулевой задержкой, callback попадает в макротаски.

Promise, с другой стороны, использует микротаски. Когда promise резолвится, его .then() или .catch() колбэки ставятся в очередь микротасок. Эта очередь обрабатывается после завершения текущего синхронного кода, но перед следующей макротаской. Это означает, что даже зарезолвленный promise не выполнится, пока не закончится весь синхронный код, включая синхронные callback'и.

В Node.js порядок выполнения: синхронный код → микротаски (promise callbacks, process.nextTick) → макротаски (setTimeout, setImmediate, I/O callbacks). Callback'и из синхронных API выполняются на первом этапе, promise - на втором.

На практике

Этот порядок важен при проектировании архитектуры приложения. Если вы передаёте callback в синхронную функцию, он выполнится до любого promise, даже если promise уже зарезолвлен. Это может привести к неожиданным багам, если код предполагает асинхронное выполнение.

При работе с Node.js и асинхронными операциями (файловая система, сетевые запросы) callback'и из I/O операций попадают в макротаски, а promise - в микротаски. Это влияет на порядок обработки данных и может вызвать race conditions, если не учитывать приоритеты.

В современных приложениях предпочтение отдаётся promise и async/await, так как они обеспечивают более предсказуемый порядок выполнения и лучшую читаемость. Однако понимание разницы критично при отладке и оптимизации производительности.

Пример кода

JAVASCRIPT
console.log('1: синхронный код');
setTimeout(() => {
console.log('4: setTimeout callback (макротаска)');
}, 0);
Promise.resolve().then(() => {
console.log('3: promise callback (микротаска)');
});
function syncCallback(cb) {
cb();
}
syncCallback(() => {
console.log('2: синхронный callback');
});
// Вывод:
// 1: синхронный код
// 2: синхронный callback
// 3: promise callback
// 4: setTimeout callback

Как отвечать на собеседовании

Начните с прямого ответа: callback сработает раньше. Объясните разницу между синхронным и асинхронным выполнением. Упомяните event loop, очереди микротасок и макротасок. Приведите пример с кодом, демонстрирующим порядок. Подчеркните, что это не просто теоретическое знание - это влияет на реальное поведение приложения, особенно при работе с Node.js и асинхронными операциями. Если спросят про process.nextTick, упомяните, что он имеет ещё более высокий приоритет, чем promise.

Что проверяет интервьюер

Интервьюер проверяет понимание event loop, очередей выполнения и различий между синхронными и асинхронными паттернами. Это фундаментальное знание для senior-разработчика, работающего с Node.js. Также проверяется способность объяснить сложную концепцию простыми словами и привести практические примеры. Ошибка в этом вопросе может указывать на поверхностное понимание асинхронности в JavaScript.

Типичные ошибки

  • Утверждение, что promise выполняется быстрее из-за асинхронности - наоборот, асинхронность откладывает выполнение.
  • Путаница между микротасками и макротасками - promise относится к микротаскам, а не к макротаскам.
  • Игнорирование разницы между синхронными и асинхронными callback'ами - синхронный callback выполняется немедленно, асинхронный - в зависимости от API.
  • Непонимание, что зарезолвленный promise всё равно откладывает выполнение .then() до следующей микротаски.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью