В какой буфер попадает callback
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В какой буфер попадает callback
Этот вопрос относится к системе управления асинхронными операциями в JavaScript — Event Loop и различные очереди обработки колбэков. Понимание этого механизма критично для написания предсказуемого кода.
Event Loop и очереди
JavaScript использует три основные очереди для управления выполнением кода:
1. Call Stack (Стек вызовов)
Основной стек, где выполняется синхронный код:
function first() {
second();
console.log("First");
}
function second() {
console.log("Second");
}
first();
// Вывод: Second, First
2. Microtask Queue (Очередь микротасков)
Это первая асинхронная очередь, которая обрабатывается после выполнения текущего стека, но до Macrotask Queue.
В Microtask Queue попадают:
- Promise.then() / Promise.catch() / Promise.finally()
- async/await (это синтаксический сахар над Promises)
- queueMicrotask() — явное добавление в очередь
- MutationObserver — отслеживание изменений DOM
console.log("Start");
Promise.resolve()
.then(() => console.log("Promise 1"))
.then(() => console.log("Promise 2"));
console.log("End");
// Вывод:
// Start
// End
// Promise 1
// Promise 2
3. Macrotask Queue (Очередь макротасков)
Это вторая асинхронная очередь, которая обрабатывается после полной очистки Microtask Queue.
В Macrotask Queue попадают:
- setTimeout() / setInterval()
- setImmediate() (Node.js)
- requestAnimationFrame() (браузер)
- I/O операции (чтение файлов, сетевые запросы)
- UI рендеринг
- Event handlers (клики, события)
console.log("Start");
setTimeout(() => {
console.log("Timeout");
}, 0);
Promise.resolve()
.then(() => console.log("Promise"));
console.log("End");
// Вывод:
// Start
// End
// Promise
// Timeout
Визуализация Event Loop
console.log("Script start");
setTimeout(() => {
console.log("setTimeout 1");
}, 0);
Promise.resolve()
.then(() => {
console.log("Promise 1");
setTimeout(() => console.log("setTimeout 2"), 0);
})
.then(() => console.log("Promise 2"));
console.log("Script end");
// Вывод:
// Script start
// Script end
// Promise 1
// Promise 2
// setTimeout 1
// setTimeout 2
Порядок выполнения
- Синхронный код (Call Stack) выполняется первым
- Microtask Queue полностью очищается (все Promises)
- UI рендеринг (если необходимо)
- Одна задача из Macrotask Queue выполняется
- Переход к шагу 2
requestAnimationFrame специальный случай
requestAnimationFrame — это гибрид между Microtask и Macrotask:
console.log("Start");
requestAnimationFrame(() => console.log("rAF"));
Promise.resolve()
.then(() => console.log("Promise"));
setTimeout(() => console.log("Timeout"), 0);
console.log("End");
// Вывод:
// Start
// End
// Promise
// rAF
// Timeout
Практический пример из React
function MyComponent() {
const handleClick = () => {
console.log("1. Click handler");
setTimeout(() => console.log("4. Timeout"), 0);
Promise.resolve()
.then(() => console.log("3. Promise"));
console.log("2. Sync code");
};
return <button onClick={handleClick}>Click me</button>;
}
// При клике на кнопку:
// 1. Click handler
// 2. Sync code
// 3. Promise
// 4. Timeout
Лучшие практики
- Используй async/await вместо .then() для читаемости
- Избегай глубокой вложенности обещаний
- Понимай порядок выполнения при работе с таймерами и Promises
- Используй queueMicrotask() только когда это действительно необходимо
- Профилируй производительность для операций в Event Loop
Знание этого механизма помогает избежать race conditions и неожиданного поведения асинхронного кода.