В какой момент callback из setTimeout попадает в Event Loop
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В какой момент callback из setTimeout попадает в Event Loop
Понимание Event Loop
Event Loop — это механизм, который позволяет JavaScript (однопоточному языку) выполнять асинхронные операции. Он постоянно проверяет, есть ли задачи для выполнения, и распределяет их на выполнение между стеком вызовов и различными очередями.
Порядок попадания setTimeout в Event Loop
Когда вы вызываете setTimeout(), callback не сразу попадает в Event Loop. Происходит следующее:
- Регистрация в Web API —
setTimeout()передаёт ваш callback в Web API (таймер браузера или Node.js) - Ожидание времени — Web API ждёт указанное время (в миллисекундах)
- Попадание в Queue — когда время истекло, callback попадает в Callback Queue (макротаска)
- Проверка Event Loop — Event Loop видит, что Call Stack пуст, и берёт callback из очереди
- Выполнение — callback выполняется в основном потоке
Пример с временной шкалой
console.log("1. Start");
setTimeout(() => {
console.log("3. setTimeout callback");
}, 100);
Promise.resolve().then(() => {
console.log("2. Promise callback");
});
console.log("4. End");
Вывод:
1. Start
4. End
2. Promise callback
3. setTimeout callback
Почему такой порядок?
- Синхронный код (1, 4) выполняется сразу
- Promise (Microtask) выполняется перед Macrotask (setTimeout)
- setTimeout (100ms) попадает в Event Loop только после истечения времени и пустого Call Stack
Микротаски vs Макротаски
Микротаски (Microtask Queue) — выше приоритет:
Promise(then, catch, finally)MutationObserverqueueMicrotask()
Макротаски (Macrotask Queue / Callback Queue) — ниже приоритет:
setTimeoutsetIntervalsetImmediate(Node.js)- I/O операции
- UI события
Ключевой момент: "0" в setTimeout
setTimeout(() => {
console.log("Выполнится не сразу");
}, 0);
Даже с задержкой 0, callback не выполнится сразу. Он попадёт в Callback Queue и будет выполнен:
- После текущего синхронного кода
- После всех микротасок
- После отрисовки (если нужна)
Визуализация Event Loop
// Call Stack пуст?
// Нет → Выполняй синхронный код
// Да ↓
// Есть микротаски?
// Да → Выполняй все микротаски
// Нет ↓
// Отрисовать UI?
// Да → Отрисуй
// Нет ↓
// Есть макротаски?
// Да → Выполняй одну макротаску → Повторяй цикл
// Нет → Ждёшь
Практический пример
console.log("Start");
setTimeout(() => {
console.log("setTimeout 0");
}, 0);
Promise.resolve()
.then(() => {
console.log("Promise 1");
})
.then(() => {
console.log("Promise 2");
});
console.log("End");
Вывод:
Start
End
Promise 1
Promise 2
setTimeout 0
Этот пример демонстрирует, что callback из setTimeout попадает в Event Loop только после выполнения всех синхронных операций и всех микротасок.
Заключение
Callback из setTimeout попадает в Event Loop не в момент вызова функции, а в момент, когда:
- Истекло время ожидания (или 0ms, но это всё равно асинхронно)
- Web API передаёт callback в Callback Queue
- Event Loop проверяет Call Stack и видит, что он пуст
- Event Loop берёт callback из Callback Queue и выполняет его
Это ключевое понимание помогает избежать проблем с асинхронным кодом и правильно предсказывать порядок выполнения операций.