Event loop

이벤트 루프

When the call stack empties, the event loop drains microtasks before taking the next task.

···
html
<div class="demo"><div class="head"><strong>EVENT LOOP</strong><span id="out">output: —</span></div><div class="scene"><div class="lane chip" id="stack">STACK<br><b>sync</b></div><span class="arrow">→</span><div class="lane chip" id="micro">MICROTASK<br><b>Promise</b></div><span class="arrow">→</span><div class="lane chip" id="task">TASK<br><b>timer</b></div></div><div class="foot"><span>sync → Promise → timer</span><span>tap to step</span></div></div>
css
.demo{width:min(92vw,660px);height:min(86vh,310px);border:1px solid var(--line);border-radius:14px;background:var(--surface);padding:clamp(10px,2.5vmin,20px);display:flex;flex-direction:column;gap:clamp(6px,1.7vmin,12px);box-shadow:0 10px 35px rgba(0,0,0,.07);font:500 clamp(10px,2.8vmin,15px)/1.35 ui-monospace,SFMono-Regular,Consolas,monospace}
.head,.foot{display:flex;align-items:center;justify-content:space-between;gap:8px}.head strong{color:var(--accent);font-size:1.05em}.foot{color:var(--muted);font-size:.85em;min-height:1.4em}.scene{flex:1;min-height:0;position:relative;display:flex;align-items:center;justify-content:center;gap:clamp(5px,1.5vmin,12px)}.chip{border:1px solid var(--line);background:var(--bg);border-radius:7px;padding:.4em .6em;text-align:center}.on{border-color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 12%,var(--surface))!important;color:var(--accent)!important}.dim{opacity:.42}.arrow{color:var(--muted)}
.lane{width:28%;height:55%;min-height:48px;display:flex;flex-direction:column;justify-content:center;gap:.5em}.lane b{font-size:1.08em}.arrow{font-size:1.3em}
js
const ids=["stack","micro","task"],names=["sync","Promise","timer"];let step=0;function advance(){ids.forEach((id,i)=>document.getElementById(id).classList.toggle("on",i===step));document.getElementById("out").textContent="output: "+names.slice(0,step+1).join(" · ");step=(step+1)%3}advance();const timer=setInterval(advance,900);document.querySelector(".demo").addEventListener("pointerdown",()=>{clearInterval(timer);advance()})

JavaScript runs synchronous code on the call stack. Promise callbacks enter the microtask queue; timer callbacks enter the task queue. Once the stack empties, the loop drains microtasks first.

The demo moves synchronous code, a Promise callback, and a timer callback in execution order. A timer scheduled for 0 ms still waits behind the current stack and its microtasks.

When to use

Use this model to predict Promise versus timer output and to diagnose UI stalls caused by long synchronous work.

Open as page ↗