🧱 Суть

queueMicrotask() позволяет отложить выполнение функции до конца текущего синхронного кода, но выполнить её раньше обычных отложенных задач (setTimeout).

📦 Проблема

Иногда нужно выполнить действие после завершения текущих обновлений состояния или синхронной логики.

Например:

appStore.closeModal();
navigate('/');

Если closeModal() вызывает изменение состояния, React может ещё не успеть завершить обновление, а navigate() уже выполнится.

✅ Решение

Использовать queueMicrotask():

queueMicrotask(() => navigate('/'));

Теперь переход произойдёт после завершения текущего стека вызовов.

💻 Код

Как работает Event Loop

Синхронный код

Выполняется сразу:

console.log('A');
console.log('C');

Microtask Queue

Сюда попадают:

  • queueMicrotask
  • Promise.then
  • MutationObserver
    Они выполняются после текущего кода.

Macrotask Queue

Сюда попадают:

  • setTimeout
  • setInterval
  • события браузера
    Они выполняются позже.

Пример

console.log('A');
 
queueMicrotask(() => {
  console.log('B');
});
 
console.log('C');

Результат:

A
C
B

B выполнится после основного кода, но раньше:

setTimeout(() => console.log('D'), 0);

queueMicrotask vs setTimeout

setTimeout

setTimeout(() => {
  navigate('/');
}, 0);

Создаёт macrotask.

Минус:

  • выполнится позже;
  • может ждать очередь браузерных событий.

queueMicrotask

queueMicrotask(() => {
  navigate('/');
});

Создаёт microtask.

Плюсы:

  • выполняется быстрее;
  • подходит для последовательных обновлений состояния;
  • сохраняет текущий контекст выполнения.

Аналог через Promise

То же самое можно написать:

Promise.resolve().then(() => navigate('/'));

Но для одного отложенного действия читаемее:

queueMicrotask(() => navigate('/'));

Пример с React

Проблемный вариант:

const logout = () => {
  appStore.closeModal();
  navigate('/');
};

Возможная проблема:

closeModal()

изменение состояния

React готовит обновление
 
navigate()

переход выполняется раньше завершения обновления

Вариант с queueMicrotask:

const logout = () => {
  appStore.closeModal();
 
  queueMicrotask(() => {
    navigate('/');
  });
};

Порядок:

closeModal()

текущий синхронный код заканчивается

microtask queue

navigate()

🎯 Вывод

  • queueMicrotask() откладывает выполнение до конца текущего тика.
  • Это быстрее и точнее, чем setTimeout(..., 0).
  • Используется, когда нужно дождаться завершения текущих синхронных операций.
  • Хорошо подходит для случаев с React state updates, MobX и последовательными действиями.

🔗 Связано