Skip to main content

Блокування поточної функції через await

Коротка відповідь

await не блокує потік виконання JavaScript, але призупиняє лише ту async-функцію, у якій він перебуває.

Чому так? Тому що JS виконує код в одному потоці, але керує завданнями через черги подій (Event Loop). await просто ставить "паузи" в коді, перетворюючи частину функції, що залишилась, на мікротаску, і повертає керування назад рушію, щоб той міг виконувати інший код.


Як це відбувається під капотом

  1. Коли рушій зустрічає await promise, він призупиняє виконання поточної async-функції.

  2. Замість цього:

  • створює мікротаску (колбек), яка має продовжити виконання функції після завершення проміса;
  • повертає керування в Event Loop (звільняє стек).
  1. JS-рушій продовжує виконувати інші завдання: інші функції, обробники подій, таймери тощо.

  2. Коли проміс завершено (fulfilled або rejected), виконується мікротаска, і виконання відновлюється всередині цієї функції - саме з того місця, де стояв await.


Приклад - "пауза" всередині функції, але не у всій програмі

javascript
async function task() { console.log('Початок'); await new Promise(r => setTimeout(r, 2000)); console.log('Кінець'); } task(); console.log('Цей код виконується одразу!');

Вивід:

javascript
Початок Цей код виконується одразу! (через 2 сек) Кінець

Пояснення:

  • await призупиняє лише функцію task(), а основний потік продовжує далі.
  • JS не "зависає" - просто всередині task() створюється мікротаска, яка повернеться в чергу після завершення таймера.

Якби await блокував потік...

То весь JavaScript "завис" би на 2 секунди: жоден обробник подій, жоден setTimeout не виконався б. Але такого не відбувається: поки task() "чекає", Event Loop спокійно обробляє інші події.


Як це виглядає в Event Loop

ЕтапЩо відбувається
1task() потрапляє в Call Stack і виконує код до await
2На await → функція "заморожується", створюється мікротаска
3Stack очищається → інші скрипти продовжують виконуватися
4Коли проміс завершується → мікротаска повертається в чергу
5Після поточного тику Event Loop → виконується решта коду task()

Приклад з паралельним кодом

javascript
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');

Вивід:

javascript
foo start bar start main thread (через 0.5с) bar end (через 1с) foo end

await не заважає виконанню інших функцій. Кожна функція просто "заморожується" до свого проміса, а потім продовжує роботу незалежно.


Приклад "мікротаски відновлення"

javascript
async function demo() { console.log('A'); await Promise.resolve(); console.log('B'); } demo(); console.log('C');

Результат:

javascript
A C B

Чому:

  • A - синхронно;
  • await "зупиняє" функцію і ставить B у чергу мікротасок;
  • основний потік виконує C;
  • потім виконуються мікротаски - B.

Проста аналогія

Уяви, що async-функція - це серіал.

Коли в серії трапляється await, серіал ставиться на паузу, але решта серіалів продовжують іти на інших каналах.

Потім, коли потрібний проміс готовий, серія продовжується рівно з того місця, де зупинилась.


Підсумок

Що робить awaitЧого не робить
Призупиняє лише поточну async-функціюНе блокує потік JavaScript
Повертає керування Event LoopНе заважає іншим завданням виконуватися
Після завершення проміса - відновлює виконанняНе "заморожує" весь застосунок
Реалізовано через мікротаски (PromiseJobs)Не використовує потоки чи sleep

Тобто await - це асинхронна пауза, а не "блокування потоку".

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.