Блокування поточної функції через await
Коротка відповідь
awaitне блокує потік виконання JavaScript, але призупиняє лише туasync-функцію, у якій він перебуває.
Чому так? Тому що JS виконує код в одному потоці, але керує завданнями через черги подій (Event Loop). await просто ставить "паузи" в коді, перетворюючи частину функції, що залишилась, на мікротаску, і повертає керування назад рушію, щоб той міг виконувати інший код.
Як це відбувається під капотом
-
Коли рушій зустрічає
await promise, він призупиняє виконання поточноїasync-функції. -
Замість цього:
- створює мікротаску (колбек), яка має продовжити виконання функції після завершення проміса;
- повертає керування в Event Loop (звільняє стек).
-
JS-рушій продовжує виконувати інші завдання: інші функції, обробники подій, таймери тощо.
-
Коли проміс завершено (
fulfilledабоrejected), виконується мікротаска, і виконання відновлюється всередині цієї функції - саме з того місця, де стоявawait.
Приклад - "пауза" всередині функції, але не у всій програмі
async function task() {
console.log('Початок');
await new Promise(r => setTimeout(r, 2000));
console.log('Кінець');
}
task();
console.log('Цей код виконується одразу!');Вивід:
Початок
Цей код виконується одразу!
(через 2 сек)
КінецьПояснення:
awaitпризупиняє лише функціюtask(), а основний потік продовжує далі.- JS не "зависає" - просто всередині
task()створюється мікротаска, яка повернеться в чергу після завершення таймера.
Якби await блокував потік...
То весь JavaScript "завис" би на 2 секунди: жоден обробник подій, жоден setTimeout не виконався б. Але такого не відбувається: поки task() "чекає", Event Loop спокійно обробляє інші події.
Як це виглядає в Event Loop
| Етап | Що відбувається |
|---|---|
| 1 | task() потрапляє в Call Stack і виконує код до await |
| 2 | На await → функція "заморожується", створюється мікротаска |
| 3 | Stack очищається → інші скрипти продовжують виконуватися |
| 4 | Коли проміс завершується → мікротаска повертається в чергу |
| 5 | Після поточного тику Event Loop → виконується решта коду task() |
Приклад з паралельним кодом
async function foo() {
console.log('foo start');
await new Promise(res => setTimeout(res, 1000));
console.log('foo end');
}
async function bar() {
console.log('bar start');
await new Promise(res => setTimeout(res, 500));
console.log('bar end');
}
foo();
bar();
console.log('main thread');Вивід:
foo start
bar start
main thread
(через 0.5с) bar end
(через 1с) foo endawait не заважає виконанню інших функцій. Кожна функція просто "заморожується" до свого проміса, а потім продовжує роботу незалежно.
Приклад "мікротаски відновлення"
async function demo() {
console.log('A');
await Promise.resolve();
console.log('B');
}
demo();
console.log('C');Результат:
A
C
BЧому:
A- синхронно;await"зупиняє" функцію і ставитьBу чергу мікротасок;- основний потік виконує
C; - потім виконуються мікротаски -
B.
Проста аналогія
Уяви, що
async-функція - це серіал.Коли в серії трапляється
await, серіал ставиться на паузу, але решта серіалів продовжують іти на інших каналах.Потім, коли потрібний проміс готовий, серія продовжується рівно з того місця, де зупинилась.
Підсумок
Що робить await | Чого не робить |
|---|---|
Призупиняє лише поточну async-функцію | Не блокує потік JavaScript |
| Повертає керування Event Loop | Не заважає іншим завданням виконуватися |
| Після завершення проміса - відновлює виконання | Не "заморожує" весь застосунок |
Реалізовано через мікротаски (PromiseJobs) | Не використовує потоки чи sleep |
Тобто await - це асинхронна пауза, а не "блокування потоку".
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.