Как устроен Event Loop в Node.js и чем он отличается от браузерного?
Event Loop и асинхронность
Event Loop в Node.js — это цикл libuv, который проходит по фазам и в каждой запускает свою очередь колбэков, пока есть работа.
Фазы цикла по порядку
- timers — колбэки
setTimeoutиsetInterval, срок которых наступил. - pending callbacks — отложенные системные колбэки, например часть ошибок TCP.
- idle, prepare — внутренние нужды Node.js.
- poll — получение новых событий ввода-вывода и запуск их колбэков; если очередь пуста, цикл может подождать.
- check — колбэки
setImmediate. - close callbacks — например,
socket.on('close').
Между колбэками и между фазами Node.js опустошает очереди process.nextTick и микрозадач Promise.
Отличие от браузера
В браузере цикл привязан к отрисовке: макрозадачи, микрозадачи, затем рендер. В Node.js рендера нет, зато есть строгие фазы libuv и пул потоков для файловых операций, DNS и криптографии.
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
Promise.resolve().then(() => console.log('promise'));
process.nextTick(() => console.log('tick'));
// tick, promise, затем timeout и immediate (их порядок из главного модуля не гарантирован)Коротко для собеседования
Цикл идёт по фазам: timers, poll, check и другие. Микрозадачи и nextTick выполняются между ними. Тяжёлый синхронный код блокирует весь цикл, поэтому его выносят в worker.