Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Стек вызовов в Event Loop
Event Loop — это механизм, который управляет выполнением кода в JavaScript. Стек вызовов (Call Stack) является критической частью этого процесса.
Что такое Call Stack (стек вызовов)?
Call Stack — это структура данных, которая отслеживает, какие функции в данный момент выполняются. Она работает по принципу LIFO (Last In, First Out):
function a() {
console.log('a start');
b();
console.log('a end');
}
function b() {
console.log('b start');
c();
console.log('b end');
}
function c() {
console.log('c');
}
a();
// Порядок выполнения:
// a start
// b start
// c
// b end
// a end
Стек вызовов при выполнении:
1. Global context
2. Global context, a()
3. Global context, a(), b()
4. Global context, a(), b(), c()
5. Global context, a(), b() <- c() завершена
6. Global context, a() <- b() завершена
7. Global context <- a() завершена
Event Loop архитектура
Event Loop состоит из нескольких компонентов:
- Call Stack — стек выполняемого синхронного кода
- Callback Queue — очередь асинхронных операций (setTimeout, fetch и т.д.)
- Microtask Queue — очередь микротасок (Promises, MutationObserver)
- Web APIs — асинхронные операции (XMLHttpRequest, setTimeout, fetch)
Порядок выполнения
console.log('1. Start');
setTimeout(() => {
console.log('2. setTimeout');
}, 0);
Promise.resolve()
.then(() => {
console.log('3. Promise');
});
console.log('4. End');
// Результат:
// 1. Start
// 4. End
// 3. Promise <- Microtask Queue выполняется первой
// 2. setTimeout <- Callback Queue выполняется после Microtask Queue
Как работает Event Loop
// Пример сложной асинхронности
console.log('Script start');
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log('Data:', data);
});
setTimeout(() => {
console.log('Timeout 1');
}, 0);
Promise.resolve()
.then(() => {
console.log('Promise 1');
})
.then(() => {
console.log('Promise 2');
});
setTimeout(() => {
console.log('Timeout 2');
}, 0);
console.log('Script end');
// Порядок выполнения:
// 1. Script start <- Call Stack
// 2. Script end <- Call Stack
// 3. Promise 1 <- Microtask Queue
// 4. Promise 2 <- Microtask Queue
// 5. Data: {...} <- fetch.then (Microtask)
// 6. Timeout 1 <- Callback Queue
// 7. Timeout 2 <- Callback Queue
Визуализация Event Loop
┌──────────────────────────────────────┐
│ JAVASCRIPT ENGINE │
├──────────────────────────────────────┤
│ Call Stack (синхронный код) │
│ ┌────────────────────────────────┐ │
│ │ function a() │ │
│ │ function b() │ │
│ │ console.log() │ │
│ └────────────────────────────────┘ │
├──────────────────────────────────────┤
│ Microtask Queue (Promises) │
│ ┌────────────────────────────────┐ │
│ │ .then() │ │
│ │ async/await │ │
│ └────────────────────────────────┘ │
├──────────────────────────────────────┤
│ Callback Queue (setTimeout) │
│ ┌────────────────────────────────┐ │
│ │ setTimeout callback │ │
│ │ fetch callback │ │
│ └────────────────────────────────┘ │
├──────────────────────────────────────┤
│ Web APIs (асинхронные операции) │
└──────────────────────────────────────┘
Stack Overflow
Если стек растёт бесконечно, происходит Stack Overflow:
// Рекурсия без базового случая
function infinite() {
infinite();
}
infinite(); // RangeError: Maximum call stack size exceeded
Правильная рекурсия с базовым случаем:
function factorial(n) {
if (n === 1) return 1; // Базовый случай
return n * factorial(n - 1);
}
console.log(factorial(5)); // 120
Практический пример: сложное асинхронное выполнение
async function fetchData() {
console.log('1. Fetch started');
const response = await fetch('https://api.example.com/data');
console.log('2. Response received');
const data = await response.json();
console.log('3. Data parsed');
return data;
}
fetchData();
console.log('4. Main execution');
// Результат:
// 1. Fetch started <- Call Stack
// 4. Main execution <- Call Stack (async функция передана в Microtask)
// 2. Response received <- Microtask (await разрешилась)
// 3. Data parsed <- Microtask (await разрешилась)
Оптимизация Event Loop
// Плохо: блокирует Event Loop
for (let i = 0; i < 1000000; i++) {
// тяжёлые вычисления
}
// Хорошо: разбить на чанки
function processChunk(startIndex, endIndex) {
for (let i = startIndex; i < endIndex; i++) {
// вычисления
}
if (endIndex < totalItems) {
setTimeout(() => {
processChunk(endIndex, endIndex + 100);
}, 0);
}
}
processChunk(0, 100);
Основные моменты
- Call Stack — часть engine, выполняет синхронный код
- Microtask Queue — выполняется после Call Stack, перед Callback Queue
- Callback Queue — асинхронные операции (setTimeout, setInterval)
- Event Loop — проверяет, пуст ли Call Stack, затем берёт из очередей
- Приоритет: Call Stack > Microtask Queue > Callback Queue
Вывод
Call Stack — это ключевой компонент Event Loop, который отслеживает выполнение функций. Понимание взаимодействия между Call Stack, Microtask Queue и Callback Queue критично для написания эффективного асинхронного JavaScript кода.