Skip to main content

Як працює "мікротаска проміса"?

Що таке мікротаска

Мікротаска (microtask) - це маленька задача, яка виконується після поточного стеку викликів, але до того, як рушій перейде до макротасок (наприклад setTimeout, setInterval, fetch тощо).

Простіше кажучи: Мікротаски - це "черга термінових задач", які виконуються одразу після поточного коду, перш ніж почнеться "наступний тик" Event Loop.

Проміси створюють мікротаски

Коли проміс переходить у стан fulfilled або rejected, його обробники .then() / .catch() / .finally() не виконуються одразу, а ставляться в чергу мікротасок (Microtask Queue).

Приклад

javascript
console.log('1'); Promise.resolve().then(() => console.log('2')); console.log('3');

Результат:

javascript
1 3 2

Чому так:

  1. Спочатку виконується весь синхронний код (у стеку викликів).
  2. Потім Event Loop бачить, що стек порожній, і виконує всі мікротаски (у цьому випадку .then()).

Де створюються мікротаски

Мікротаски створюються:

  • при .then(), .catch(), .finally() у Promise,
  • при queueMicrotask(fn),
  • при MutationObserver (у браузері),
  • при process.nextTick() у Node.js.

Черга мікротасок і макротасок

Рушій JS обробляє події так:

  1. Виконує весь синхронний код (Call Stack).
  2. Виконує всі мікротаски, поки черга не порожня.
  3. Переходить до однієї макротаски (наприклад, setTimeout).
  4. Знову виконує всі мікротаски, що накопичилися після неї.
  5. І так по колу.

Приклад: порівняння з макротасками

javascript
console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D');

Вивід:

javascript
A D C B

Чому:

  1. A, D - синхронно;
  2. C - мікротаска (від проміса);
  3. B - макротаска (від setTimeout).

Мікротаска (C) виконується раніше за таймер (B).

Приклад з кількома мікротасками

javascript
Promise.resolve().then(() => console.log('1')); Promise.resolve().then(() => console.log('2')); Promise.resolve().then(() => console.log('3')); console.log('4');

Вивід:

javascript
4 1 2 3

Усі .then() потрапляють в одну чергу мікротасок, і виконуються у порядку додавання, після завершення синхронного коду (4).

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

javascript
Promise.resolve().then(() => { console.log('A'); Promise.resolve().then(() => console.log('B')); });

Вивід:

javascript
A B

Чому:

  • Після A виконується нова мікротаска (B), додана під час виконання попередньої.

Важливе правило

Після виконання кожної макротаски рушій завжди повністю виконує всі мікротаски, перш ніж узяти наступну макротаску.

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

Уяви, що Event Loop - це черга в кафе.

  • "Макротаски" - це звичайні замовлення (великі).
  • "Мікротаски" - це швидка решта і розрахунок.

Бариста робить замовлення (синхронний код), потім видає всю решту (мікротаски), і лише потім переходить до наступного клієнта (нової макротаски).

Підсумок

Тип задачіПрикладиКоли виконується
Мікротаски.then(), .catch(), .finally(), queueMicrotask()Після поточного коду, до наступної макротаски
МакротаскиsetTimeout, setInterval, fetch, події DOMПісля всіх мікротасок поточного тика

Проміси завжди використовують мікротаски, тому їхні колбеки виконуються раніше, ніж таймери.

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

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

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