Înțelegerea modului în care funcționează Event Loop în motoarele JavaScript (V8 din Chrome/Node.js, JavaScriptCore din Safari, SpiderMonkey din Firefox) este diferența dintre un dezvoltator junior și unul senior. Deși JavaScript rulează pe un singur fir de execuție principal (single-threaded), el realizează operațiuni asincrone masive fără blocare datorită cooperării dintre Call Stack, Web APIs și cele două cozi de execuție: Microtasks și Macrotasks.
console.log("1. Start Sincron");
setTimeout(() => {
console.log("2. Macrotask (setTimeout)");
}, 0);
Promise.resolve().then(() => {
console.log("3. Microtask 1 (Promise)");
}).then(() => {
console.log("4. Microtask 2 (Promise înlănțuit)");
});
queueMicrotask(() => {
console.log("5. Microtask direct (queueMicrotask)");
});
console.log("6. Final Sincron");
// ORDINEA REALĂ DE AFIȘARE:
// 1. Start Sincron
// 6. Final Sincron
// 3. Microtask 1 (Promise)
// 5. Microtask direct (queueMicrotask)
// 4. Microtask 2 (Promise înlănțuit)
// 2. Macrotask (setTimeout)
De ce au Microtask-urile Prioritate Absolută
Regula de aur a ciclului Event Loop este:
- Execută codul sincron din Call Stack până când stiva este complet goală.
- Verifică Microtask Queue: dacă există sarcini (callback-uri de
Promise,queueMicrotask,MutationObserver), execută TOATE microtask-urile până la golirea completă a cozii. Dacă un microtask adaugă alt microtask, acesta va fi executat în același ciclu! - Dacă este momentul pentru actualizarea ecranului (la 60 sau 120 Hz), rulează etapa de Render / Paint a browserului.
- Extrage și execută exact UN SINGUR macrotask din Macrotask Queue (
setTimeout,setInterval, evenimente I/O). - Reia ciclul de la pasul 2.
Capcană Frecventă: Blocarea Browserului prin Microtask Loop Infinit
Dacă programezi recursiv un microtask (de exemplu o promisiune care se rezolvă la infinit chemând queueMicrotask), browserul se va bloca complet, deoarece Event Loop nu va ajunge niciodată la etapa de Render și nici la prelucrarea evenimentelor de click ale utilizatorului.