Gernar
JavaScript: асинхронность

Как распределяются по очереди задач синхронный код

Разбор вопроса «Как распределяются по очереди задач синхронный код» для Frontend Developer: что проверяет интервьюер, ключевые тезисы, практические примеры и частые ошибки.

Вопрос

Как распределяются по очереди задач синхронный код

Профессия

Frontend Developer

Что хочет услышать интервьюер

Интервьюер хочет убедиться, что кандидат понимает базовый принцип работы Event Loop и очередности выполнения задач в JavaScript, включая разницу между синхронным и асинхронным кодом.

Ключевые тезисы

  • Синхронный код выполняется последовательно, строка за строкой, в порядке его написания.
  • Каждая синхронная задача попадает в Call Stack (стек вызовов) и выполняется немедленно, блокируя дальнейшее выполнение кода до своего завершения.
  • Синхронные операции имеют приоритет над асинхронными, так как они не требуют ожидания (например, API-запросов или таймеров).
  • После выполнения синхронного кода Event Loop проверяет очередь задач (Task Queue) и начинает выполнять асинхронные задачи (например, колбэки из setTimeout или Promise).

Подробный ответ

Синхронный код в JavaScript выполняется последовательно, строка за строкой, в том порядке, в котором он написан. Каждая синхронная задача попадает в Call Stack (стек вызовов) и выполняется немедленно. Call Stack — это структура данных, которая отслеживает текущий контекст выполнения. Когда функция вызывается, она добавляется в стек, а когда завершает выполнение — удаляется из него. Синхронный код блокирует дальнейшее выполнение программы до своего завершения, так как он не требует ожидания внешних событий, таких как API-запросы или таймеры. После завершения выполнения синхронного кода Event Loop начинает проверять очередь задач (Task Queue) и обрабатывать асинхронные задачи, такие как колбэки из setTimeout или Promise. Event Loop — это механизм, который управляет выполнением асинхронного кода, проверяя, пуст ли Call Stack, и перемещая задачи из очереди в стек для выполнения. Синхронный код имеет приоритет над асинхронным, так как он выполняется немедленно, не требуя ожидания.

Практические примеры

Пример 1

Синхронный код блокирует выполнение асинхронного.

console.log('Начало');
setTimeout(() => console.log('Таймер'), 0);
console.log('Конец');
// Вывод: Начало, Конец, Таймер

Здесь синхронный код выполняется первым, а setTimeout, хотя и имеет задержку 0, попадает в очередь задач и выполняется после завершения синхронного кода.

Пример 2

Пример с ошибкой в синхронном коде.

console.log('Начало');
throw new Error('Ошибка!');
console.log('Конец');
// Вывод: Начало, затем выбрасывается ошибка, и 'Конец' не выполняется.

Если в синхронном коде возникает ошибка, выполнение кода прекращается, и асинхронные задачи не выполняются, пока ошибка не будет обработана.

Частые ошибки

  • Ошибка: Непонимание того, что синхронный код всегда выполняется перед асинхронным, даже если асинхронный код имеет нулевую задержку.
  • Ошибка: Игнорирование того, что ошибка в синхронном коде может полностью остановить выполнение программы, включая асинхронные задачи.

Связанные темы

  • Event Loop и его роль в асинхронном выполнении кода.
  • Разница между микротасками (microtasks) и макротасками (macrotasks) в контексте Event Loop.
  • Работа с ошибками в JavaScript и использование try/catch для обработки исключений.

Follow-up вопросы

Что такое Call Stack и как он работает?

Уровень: basic

Call Stack — это структура данных, которая хранит информацию о вызовах функций. Когда функция вызывается, она помещается в стек, а когда завершается — удаляется из него. Синхронный код выполняется в порядке LIFO (Last In, First Out).

Как Event Loop обрабатывает асинхронный код после выполнения синхронного?

Уровень: intermediate

Event Loop проверяет Call Stack и Task Queue. Если Call Stack пуст, он берет первую задачу из Task Queue (например, колбэк из setTimeout) и помещает ее в Call Stack для выполнения. Это гарантирует неблокирующее выполнение асинхронного кода.

Может ли синхронный код блокировать Event Loop? Приведите пример.

Уровень: intermediate

Да, например, бесконечный цикл или тяжелые вычисления в синхронном коде заблокируют Event Loop, так как Call Stack не освободится. Это приведет к «зависанию» интерфейса и невозможности выполнения асинхронных задач.

Как микротаски (microtasks) отличаются от макротасок (macrotasks) в контексте Event Loop?

Уровень: advanced

Микротаски (например, колбэки Promise.then) выполняются сразу после текущей синхронной задачи, до перехода к макротаскам (setTimeout, setInterval). Они имеют приоритет и обрабатываются в отдельной очереди — Microtask Queue.

Что произойдет, если в синхронном коде выбросить ошибку? Как это повлияет на очередь задач?

Уровень: intermediate

Синхронная ошибка прервет выполнение текущего блока кода, и Call Stack очистится. Event Loop продолжит работу, но последующий синхронный код после ошибки не выполнится. Асинхронные задачи из очереди обработаются, если ошибка не была перехвачена.

Содержание