029
LVL 01 — WAVE DEFENDER SESSION 029 DAY 29

THE EVENT LOOP

🎫 PIXELCRAFT-017
🐛 Bug / ⚡ Performance | 🟡 Medium | Priority: 🔴 Critical

Applying any filter on a large image freezes the browser for 3–5 seconds. The UI is completely unresponsive — buttons don't work, the cursor spins. Users think the app crashed.
CONCEPTS.UNLOCKED
🧵
Why the UI Freezes
JavaScript is single-threaded — one long loop blocks everything. The browser can't repaint, respond to clicks, or update the cursor until your loop finishes.
🔄
The Event Loop
Call stack → task queue → microtask queue → render. JavaScript processes one task at a time. When the call stack is empty, it picks the next task from the queue.
setTimeout(fn, 0)
Yield to the browser, then continue. Puts fn in the task queue instead of running it immediately. The browser gets a chance to repaint and handle events between chunks.
🧩
Async Chunk Processing
Break a big job into small pieces. Process one chunk, yield to the browser, process the next chunk. The UI stays responsive throughout.
📊
Progress Indicators
Show users something is happening. "Processing... 45%" with a progress bar. Without feedback during long operations, users assume the app is broken.
🧪
Execution Order Prediction
console.log("A"); setTimeout(() => console.log("B"), 0); console.log("C"); → outputs A, C, B. Understanding why = understanding the event loop.
HANDS-ON.TASKS
01
Reproduce the Freeze

Apply a filter to a 4K image → frozen for 5 seconds.

Why: the for loop over 33 million values runs without giving the browser a chance to update the UI or respond to clicks.

02
Visualize the Event Loop
Call Stack: [applyFilter → for loop (33M iterations)] Task Queue: [click event, mousemove, repaint] ← WAITING (blocked!)
The loop blocks the stack. Nothing else can run until it finishes. Click events, repaints, cursor updates — all queued and waiting. This is why the UI freezes.
03
Break into Chunks
function applyFilterAsync(imageData, filterFn, onComplete) { const pixels = imageData.data; const chunkSize = 100000; // Process 100K pixels per chunk let offset = 0; function processChunk() { const end = Math.min(offset + chunkSize * 4, pixels.length); for (let i = offset; i < end; i += 4) { const [newR, newG, newB] = filterFn( pixels[i], pixels[i+1], pixels[i+2] ); pixels[i] = clamp(newR); pixels[i + 1] = clamp(newG); pixels[i + 2] = clamp(newB); } offset = end; if (offset < pixels.length) { const progress = Math.round( (offset / pixels.length) * 100 ); updateProgressBar(progress); setTimeout(processChunk, 0); // Yield to browser } else { onComplete(); } } processChunk(); }
setTimeout(processChunk, 0) doesn't run immediately — it puts processChunk in the task queue. Between chunks, the browser can repaint, handle clicks, and update the progress bar.
04
Add a Progress Bar

Show "Processing... 45%" with a visual progress bar that fills as chunks complete.

Test: UI stays responsive during processing! Buttons still work.

05
Predict Execution Order
console.log("A"); setTimeout(() => console.log("B"), 0); console.log("C"); // Output: A, C, B — why?

A runs immediately (call stack). setTimeout puts B in the task queue. C runs next (still on the call stack). Only after the stack is empty does the event loop pick B from the queue.

06
Close the Ticket
git switch -c perf/PIXELCRAFT-017-async-processing git add src/scripts/ src/styles/ git commit -m "Async chunk processing with progress bar (PIXELCRAFT-017)" git push origin perf/PIXELCRAFT-017-async-processing # PR → Review → Merge → Close ticket ✅
CS.DEEP-DIVE

The event loop is JavaScript's concurrency model.

Unlike languages with threads (Java, C++), JS uses a single thread with cooperative multitasking.

// setTimeout(fn, 0) doesn't run immediately —
// it puts fn in the task queue. The event loop
// only runs the next task after the current
// call stack is empty.

// Benefits of single-threaded + event loop:

No race conditions  (common in threads)
No deadlocks       (common in threads)
Simpler mental model

// Tradeoff:
Requires non-blocking patterns
(setTimeout, callbacks, Promises)

// Understanding the event loop separates
// junior from intermediate JS developers.
"Event Loop Lab"
[A] Predict the output order of this code, then verify: console.log("1"); setTimeout(() => console.log("2"), 0); Promise.resolve().then(() => console.log("3")); console.log("4");
[B] Add a "Cancel" button that stops the async filter mid-processing. Hint: use a boolean flag checked at the start of each processChunk().
[C] Watch Philip Roberts' legendary talk "What the heck is the event loop anyway?" on YouTube. Then explain the event loop to a friend using a restaurant analogy.
REF.MATERIAL
VIDEO
Philip Roberts (JSConf EU)
THE talk on the event loop. Visual, intuitive, legendary. If you watch one video about JavaScript internals, make it this one.
EVENT LOOPLEGENDARYMUST WATCH
TOOL
Philip Roberts
Interactive tool that visualizes the call stack, task queue, and event loop in real time. Paste your code and watch it execute step by step.
EVENT LOOPVISUALINTERACTIVE
ARTICLE
Mozilla Developer Network
Official reference: runtime concepts, call stack, task queues, microtasks, and the "run to completion" guarantee.
EVENT LOOPMDNREFERENCE
ARTICLE
javascript.info
Deep dive into microtasks vs macrotasks, Promise resolution order, and queueMicrotask(). Interactive examples.
MICROTASKSINTERACTIVE
VIDEO
Fireship
Rapid visual breakdown of the event loop, call stack, and task queues. A fast refresher after Philip Roberts' full talk.
EVENT LOOPQUICK
// LEAVE EXCITED BECAUSE
The app no longer freezes! Filters show a progress bar. The UI stays responsive. You cracked one of the most important concepts in JavaScript — the event loop.