Как может асинхронный код выполняться параллельно с синхронным?
Асинхронность и Event Loop
Асинхронный код не выполняется параллельно с синхронным в основном потоке — JS однопоточный. «Параллельность» кажущаяся: асинхронная операция ждёт вне потока (Web API), а её коллбэк выполняется в основном потоке позже, когда он свободен.
Однопоточность — нет истинной параллельности
В основном потоке JS выполняется одна операция за раз. Синхронный и асинхронный код не выполняются одновременно:
console.log('sync');
setTimeout(() => console.log('async'), 0);
// оба в одном потоке, async — позжеКак достигается «параллельность» ожидания
Асинхронная операция (таймер, запрос) выполняется вне JS-потока — в Web API браузера (или системе):
JS-поток: запускает fetch → продолжает синхронный код
Web API: выполняет запрос параллельно (вне JS-потока)
По готовности: коллбэк → очередь → Event Loop → JS-поток (когда свободен)То есть ожидание идёт параллельно (браузер держит соединение/таймер), но JS-коллбэк выполняется в основном потоке, не одновременно с синхронным кодом.
Что действительно параллельно
- Web API/браузер — сеть, таймеры, I/O выполняются вне JS-потока (это работа браузера, не JS).
- Web Workers — отдельные JS-потоки для настоящего параллелизма вычислений.
Итог
- Синхронный код и JS-коллбэки — последовательно в одном потоке.
- Само ожидание async-операций — параллельно (вне JS-потока, делает браузер).
- Истинный JS-параллелизм — только Web Workers.
Коротко для собеседования
В основном потоке асинхронный код не выполняется параллельно с синхронным — JS однопоточный. Параллельно идёт лишь ожидание async-операции (её выполняет Web API/браузер вне JS-потока), а коллбэк попадает в основной поток позже через Event Loop, когда он свободен. Истинный параллелизм JS-кода — только Web Workers.