> Куда пойдет выполнение при конкурентном запуске нескольких задач в JavaScript (JavaScript)

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

Компании: Black Wall Group (BWG)

Стек: JavaScript

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

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

При конкурентном запуске нескольких задач в JavaScript выполнение пойдет в event loop: синхронный код выполняется сразу, а асинхронные задачи (setTimeout, fetch, Promise) попадают в очередь микрозадач или макрозадач. Event loop последовательно обрабатывает call stack, затем очередь микрозадач (Promise, queueMicrotask), потом одну макрозадачу (setTimeout, I/O). Порядок выполнения зависит от типа задачи и фазы event loop.

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

JavaScript - однопоточный язык с моделью конкурентности на основе event loop. При запуске нескольких задач:

  1. Синхронный код выполняется немедленно в call stack, блокируя поток до завершения.

  2. Микрозадачи (Promise.then/catch/finally, queueMicrotask, MutationObserver) имеют наивысший приоритет после текущего синхронного кода. После каждого макрозадача event loop полностью опустошает очередь микрозадач перед переходом к следующему макрозадачу.

  3. Макрозадачи (setTimeout, setInterval, I/O, UI rendering) обрабатываются по одной за цикл. Event loop берет одну макрозадачу из очереди, выполняет её, затем обрабатывает все накопившиеся микрозадачи, и только потом переходит к следующей макрозадаче.

  4. requestAnimationFrame выполняется перед рендерингом, между микрозадачами и макрозадачами.

Конкурентность достигается за счет того, что асинхронные операции (сетевые запросы, таймеры) не блокируют поток - они регистрируют callback, который выполняется позже, когда данные готовы. Это позволяет обрабатывать множество задач без создания дополнительных потоков.

На практике

Для frontend-разработчика понимание event loop критично при:

  • Оптимизации производительности: длительные синхронные операции блокируют UI. Разбивайте их на части через setTimeout или используйте Web Workers для тяжелых вычислений.

  • Работе с анимациями: requestAnimationFrame гарантирует выполнение перед рендерингом, что дает плавные анимации.

  • Обработке пользовательского ввода: события (клики, скролл) - макрозадачи, но их обработчики могут порождать микрозадачи, которые выполняются до следующего рендеринга.

  • Управлении состоянием: если несколько Promise разрешаются одновременно, их then-обработчики выполняются в порядке добавления в очередь микрозадач.

  • Debounce/throttle: реализация через setTimeout создает макрозадачи, которые могут накапливаться при быстром вызове.

Пример кода

JAVASCRIPT
console.log('1: синхронный код');
setTimeout(() => {
console.log('2: макрозадача setTimeout');
}, 0);
Promise.resolve()
.then(() => {
console.log('3: микрозадача Promise');
})
.then(() => {
console.log('4: вторая микрозадача Promise');
});
queueMicrotask(() => {
console.log('5: микрозадача queueMicrotask');
});
console.log('6: еще синхронный код');
// Вывод:
// 1: синхронный код
// 6: еще синхронный код
// 3: микрозадача Promise
// 5: микрозадача queueMicrotask
// 4: вторая микрозадача Promise
// 2: макрозадача setTimeout

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

Начните с определения event loop как механизма, обеспечивающего конкурентность в однопоточном JavaScript. Объясните приоритеты: синхронный код → микрозадачи → макрозадачи. Приведите пример с Promise и setTimeout, чтобы показать порядок выполнения. Упомяните, что requestAnimationFrame выполняется между микрозадачами и рендерингом. Если спросят про Web Workers - поясните, что это настоящая параллельность, а не конкурентность.

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

  • Понимание event loop как основы асинхронности в JavaScript
  • Знание очередей микрозадач и макрозадач
  • Умение предсказывать порядок выполнения кода
  • Понимание разницы между конкурентностью и параллелизмом
  • Осознание влияния event loop на производительность UI

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

  • Путать микрозадачи и макрозадачи (например, считать setTimeout микрозадачей)
  • Думать, что setTimeout с задержкой 0 выполняется сразу после синхронного кода
  • Не учитывать, что микрозадачи обрабатываются до следующей макрозадачи
  • Считать, что event loop - это часть языка, а не среда выполнения (браузер/Node.js)
  • Игнорировать requestAnimationFrame при обсуждении рендеринга

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

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