<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Elina Dzhelilova</title>
    <description>The latest articles on Forem by Elina Dzhelilova (@elina_web_magic).</description>
    <link>https://forem.com/elina_web_magic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3376375%2F980a2bae-de4c-4afc-bb15-ef868d44001f.jpg</url>
      <title>Forem: Elina Dzhelilova</title>
      <link>https://forem.com/elina_web_magic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/elina_web_magic"/>
    <language>en</language>
    <item>
      <title>The Event Loop, Part III: The Unstoppable Train 🚂</title>
      <dc:creator>Elina Dzhelilova</dc:creator>
      <pubDate>Mon, 05 Jan 2026 18:16:29 +0000</pubDate>
      <link>https://forem.com/elina_web_magic/the-event-loop-part-iii-the-unstoppable-train-2bld</link>
      <guid>https://forem.com/elina_web_magic/the-event-loop-part-iii-the-unstoppable-train-2bld</guid>
      <description>&lt;p&gt;&lt;strong&gt;One track. One train. No overtaking.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;👋 Hey folks!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;&lt;a href="https://dev.to/elina_web_magic/the-event-loop-is-not-magic-you-just-dont-know-the-spell-31fh"&gt;Part I&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://dev.to/elina_web_magic/the-event-loop-part-ii-the-wand-is-not-yours-or-why-the-ui-ignores-you-3kgg"&gt;Part II&lt;/a&gt;&lt;/strong&gt;, we discussed the &lt;strong&gt;Illusion&lt;/strong&gt;: why browsers appear "instant" to Muggles (users) 🧑‍, and why that illusion breaks when we interact with the DOM.&lt;/p&gt;

&lt;p&gt;Now, we strip away the magic and look at the foundation.&lt;br&gt;
No Event Loop yet.&lt;br&gt;
No microtasks.&lt;br&gt;
No queues.&lt;/p&gt;

&lt;p&gt;Only the thing that &lt;strong&gt;always&lt;/strong&gt; happens first.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚂 The Call Stack is a Train That Does Not Stop
&lt;/h2&gt;

&lt;p&gt;Imagine the &lt;strong&gt;Hogwarts Express&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has &lt;strong&gt;one track&lt;/strong&gt; (The Main Thread 🧵).&lt;/li&gt;
&lt;li&gt;It moves in &lt;strong&gt;one direction&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;While the train is on the track, &lt;strong&gt;nothing else can move&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is your &lt;strong&gt;Call Stack&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt; is synchronous by nature. It is single-minded. It executes spells (code) step-by-step and &lt;strong&gt;never&lt;/strong&gt; gives up control halfway through.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The browser?&lt;/strong&gt; Sure, it’s asynchronous. It has networking, timers, the rendering engine, the GPU… But JavaScript itself? It sits comfortably in the Call Stack, blocking the view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And while the Call Stack is busy, the track is closed.&lt;/strong&gt; ⛔️&lt;/p&gt;


&lt;h2&gt;
  
  
  🧪 Scenario 1: The Sync Trap (Click vs. .click())
&lt;/h2&gt;

&lt;p&gt;Let’s look at a spell that confuses many wizards. We have a button, a listener, and some logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log("A: script start");

button.addEventListener("click", () =&amp;gt; {
  console.log("B: click start");

  // 🪄 Synchronous array magic
  const items = [1, 2, 3];
  items.map((n) =&amp;gt; {
    console.log("C: map:", n);
    return n * 2;
  });

  button.classList.add("active");
  console.log("D: class added");

  // 🦉 Future work (Async)
  Promise.resolve().then(() =&amp;gt; {
    console.log("E: Promise.then");
  });

  setTimeout(() =&amp;gt; {
    console.log("F: setTimeout");
  }, 0);

  console.log("G: click end");
});

console.log("H: before click");

// ⚠️ Crucial moment: We trigger the click SYNCHRONOUSLY
button.click();

console.log("I: after click");

console.log("J: script end");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Output 📜&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A: script start
H: before click
B: click start
C: map: 1
C: map: 2
C: map: 3
D: class added
G: click end
I: after click
J: script end
E: Promise.then
F: setTimeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Happens (The Magic Mechanics) ⚙️&lt;/strong&gt;&lt;br&gt;
Look closely at &lt;code&gt;I: after click&lt;/code&gt;. It appears after the entire click handler runs (logs &lt;code&gt;B&lt;/code&gt;, &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;D&lt;/code&gt;, and &lt;code&gt;G&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Why? Because &lt;code&gt;button.click()&lt;/code&gt; is a synchronous command.&lt;/p&gt;

&lt;p&gt;The script runs &lt;code&gt;H: before click&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It hits &lt;code&gt;button.click()&lt;/code&gt; and immediately jumps into the addEventListener function.&lt;/p&gt;

&lt;p&gt;It must finish that entire function (running through &lt;code&gt;G: click end&lt;/code&gt;) before it can return to the main flow to print &lt;code&gt;I: after click&lt;/code&gt; and &lt;code&gt;J: script end&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Rule:&lt;/strong&gt; The train is moving. Passengers (code lines) exit strictly in boarding order. &lt;code&gt;Async&lt;/code&gt; tasks (&lt;em&gt;Promises&lt;/em&gt; like &lt;code&gt;E&lt;/code&gt; and &lt;em&gt;Timeouts&lt;/em&gt; like &lt;code&gt;F&lt;/code&gt;) are thrown out of the window to catch a later train. 👋&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  🧪 Scenario 2: Immediate Magic (No Clicks)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log("A: script start");

const el = document.createElement("div");

// 🪄 Direct DOM mutation
el.classList.add("box");
console.log("B: class added");

// ⚠️ Forces Layout (Heavy synchronous calculation)
const height = el.getBoundingClientRect().height;
console.log("C: layout read", height);

Promise.resolve().then(() =&amp;gt; {
  console.log("D: Promise.then");
});

setTimeout(() =&amp;gt; {
  console.log("E: setTimeout");
}, 0);

console.log("F: script end");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Output 📜&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A: script start
B: class added
C: layout read 0
F: script end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and only then...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D: Promise.then
E: setTimeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What Matters Here 🧠&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;classList.add()&lt;/code&gt; is synchronous.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getBoundingClientRect()&lt;/code&gt; is synchronous (and expensive!). It forces the browser to calculate geometry right now.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promises&lt;/code&gt; wait. Even if they feel “instant”, they are not allowed on the current train.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No async mechanism can intervene until the Call Stack is empty.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚗 Where Render Fits In
&lt;/h2&gt;

&lt;p&gt;Rendering (Layout, Paint, Composite) is not part of the Call Stack. Think of Render as the Flying Ford Anglia 🚙 trying to cross the train tracks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Ford Anglia is hovering, ready to go.&lt;/li&gt;
&lt;li&gt;The engine is roaring (60fps needed!).&lt;/li&gt;
&lt;li&gt;The GPU is warmed up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt;: ⛔️ &lt;strong&gt;The Ford Anglia cannot cross while&lt;/strong&gt; the Hogwarts Express 🚂 (Call Stack) is &lt;strong&gt;occupying the track&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi1kmb5f63zbsz209vsb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi1kmb5f63zbsz209vsb.gif" alt="Elina · WebMagic animation: Blue Flying Ford Anglia representing the Browser Render Engine trying to fly alongside the Main Thread tracks" width="426" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It doesn’t matter how urgent the paint is. If your while loop is running, or your JSON is parsing, or your map() is iterating, the frame is dropped. The screen freezes. The illusion breaks.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧑‍🎓 Who Actually Sits in the Call Stack?
&lt;/h2&gt;

&lt;p&gt;When we say &lt;em&gt;“Call Stack”&lt;/em&gt;, we don’t mean abstract code. We mean specific synchronous operations that hog the line:&lt;/p&gt;

&lt;p&gt;✅ &lt;code&gt;Array.map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;&lt;br&gt;
✅ &lt;code&gt;for&lt;/code&gt;  &lt;code&gt;while&lt;/code&gt; loops&lt;br&gt;
✅ &lt;code&gt;classList.add()&lt;/code&gt; / &lt;code&gt;remove()&lt;/code&gt;&lt;br&gt;
✅ &lt;code&gt;getBoundingClientRect()&lt;/code&gt; / &lt;code&gt;offsetWidth&lt;/code&gt;&lt;br&gt;
✅ Any function without &lt;code&gt;await&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All of them run to completion. All of them fully occupy &lt;strong&gt;the Main Thread&lt;/strong&gt;. None of them let Render sneak in.&lt;/p&gt;

&lt;h2&gt;
  
  
  😈 Who Can Stop the Train?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Call Stack cannot stop itself.&lt;/strong&gt; Once the function starts, it runs until the closing brace.&lt;/p&gt;

&lt;p&gt;Only external &lt;strong&gt;“Dark Arts”&lt;/strong&gt; can stop it:&lt;/p&gt;

&lt;p&gt;👑 The Browser (killing a frozen tab)&lt;br&gt;
🧊 Debugger (breakpoints)&lt;br&gt;
💥 Crash (Error)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcemlc0eryzffdkpc631j.GIF" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcemlc0eryzffdkpc631j.GIF" alt="Elina · WebMagic animation: The Hogwarts Express train (Call Stack) being attacked and stopped by Death Eaters, representing heavy synchronous tasks blocking the Main Thread" width="426" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not the Event Loop. This is just... The Line.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 Part III Summary
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Synchronous execution always comes first.&lt;/li&gt;
&lt;li&gt;The Call Stack fully owns the Main Thread.&lt;/li&gt;
&lt;li&gt;Render cannot interrupt it.&lt;/li&gt;
&lt;li&gt;Promises and timers must wait for the stack to clear.&lt;/li&gt;
&lt;li&gt;The train moves until it has completed its route.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔮 What’s Next?
&lt;/h2&gt;

&lt;p&gt;We have the Line. Now we need the Loop.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part IV&lt;/strong&gt;, we finally meet the messengers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;🦉 Microtasks&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;💌 Promises&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why does the Owl (Promise) arrive before the Render, but after the sync code? Stay tuned! ✨&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Let's Discuss&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you ever accidentally frozen your browser with a while(true) loop or heavy calculation? Drop your "horror stories" in the comments! 👇&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy coding! 👩‍💻✨&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Elina · WebMagic&lt;/strong&gt; &lt;em&gt;Mastering the Dark Arts of Web Development&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Event Loop, Part II: The Wand Is Not Yours 🪄 (Or Why the UI Ignores You)</title>
      <dc:creator>Elina Dzhelilova</dc:creator>
      <pubDate>Sun, 04 Jan 2026 19:24:51 +0000</pubDate>
      <link>https://forem.com/elina_web_magic/the-event-loop-part-ii-the-wand-is-not-yours-or-why-the-ui-ignores-you-3kgg</link>
      <guid>https://forem.com/elina_web_magic/the-event-loop-part-ii-the-wand-is-not-yours-or-why-the-ui-ignores-you-3kgg</guid>
      <description>&lt;p&gt;Hey folks! 👋&lt;/p&gt;

&lt;p&gt;If you missed the start of our journey, where we discussed why the browser lies to users to keep things looking smooth, check it out here 👉 &lt;a href="https://dev.to/elina_web_magic/the-event-loop-is-not-magic-you-just-dont-know-the-spell-31fh"&gt;Part I: The Illusion&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today, we are ripping off the band-aid on a painful topic. The million-dollar question: If my code executes, why the hell doesn’t anything change on the screen?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let’s be real&lt;/em&gt;: we all live in this illusion that JavaScript is in total control. But spoiler alert: the browser often just completely ignores your commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Illusion We Don't Notice 🙈
&lt;/h2&gt;

&lt;p&gt;We are used to writing code with the expectation of "instant karma":&lt;br&gt;
🪄 I changed the DOM — show it.&lt;br&gt;
🪄 The Promise resolved — render the update!&lt;br&gt;
🪄 This line ran — the UI must reflect it.&lt;/p&gt;

&lt;p&gt;But it doesn't work like that. JavaScript can change the DOM. But &lt;em&gt;only the Browser decides whether to show those changes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It's like ordering a pizza: you can place the order (change state), but that doesn't mean the delivery driver (the renderer) is ringing your doorbell right now.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Browser is Not Just a JS Runtime 🏗️
&lt;/h2&gt;

&lt;p&gt;Modern Chrome or Firefox isn't just a "JavaScript environment." It’s a complex machine where multiple systems work in parallel:&lt;/p&gt;

&lt;p&gt;🧩 JS Engine (V8) — executes your code.&lt;br&gt;
🧩 Rendering Engine (Blink) — paints the pixels.&lt;/p&gt;

&lt;p&gt;Think of them as neighbours shouting over a fence. They are not the same person. And most importantly: &lt;strong&gt;&lt;em&gt;They share the same Main Thread.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Aunt Petunia’s Experiment 🐸
&lt;/h2&gt;

&lt;p&gt;Let’s get to the code. Imagine a classic frontend scenario:&lt;/p&gt;

&lt;p&gt;User clicks a button.&lt;br&gt;
We show a loading spinner.&lt;br&gt;
We run a heavy synchronous task (like parsing a massive JSON).&lt;br&gt;
We hide the spinner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expectation:&lt;/strong&gt; The spinner appears, spins for a bit, and vanishes. &lt;strong&gt;Reality:&lt;/strong&gt; ... 🫠&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;button.addEventListener("click", () =&amp;gt; {
  showMagicLoader(); // 🪄 Spell: "Show the spinner!"

  // ⚠️ Warning! Heavy synchronous work.
  // We are blocking the Main Thread completely.
  const response = "[" + "1,".repeat(5_000_000) + "1]";
  JSON.parse(response); // The browser is frozen here 🥶

  hideMagicLoader(); // 🪄 Spell: "Hide the spinner!"
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does the user see? Absolutely nothing. The screen just "freezes" for a second and then "unfreezes." The spinner never appeared.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frylk4dlq7fmcvbfxuyxc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frylk4dlq7fmcvbfxuyxc.gif" alt=" " width="560" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Honesty Check 🔦&lt;/em&gt;&lt;/strong&gt;: did the thought cross your mind that the spinner would appear for at least a millisecond?&lt;/p&gt;

&lt;p&gt;If yes — congratulations, you’re a normal developer 😅. I used to think that too. But here is the harsh truth:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Code Execution ≠ Rendering&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While JavaScript is busy dealing with your JSON on the Main Thread, the browser physically cannot paint anything. It is blocked. When JS finally finishes the job, it immediately executes &lt;code&gt;hideMagicLoader()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To the browser, the timeline looks like this:&lt;br&gt;
"Oh, JS changed the DOM to show a spinner... but I'm busy executing JS, I'll wait."&lt;/p&gt;

&lt;p&gt;"Yup, JS is still going..."&lt;br&gt;
"Oh, JS now says to hide the spinner. Okay."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; The spinner existed in the DOM, but it never made it to the Paint stage.&lt;/p&gt;

&lt;p&gt;It’s Not a Bug, It’s a Feature (Seriously) 😎.&lt;br&gt;
Browsers aren't optimised for us developers. They are optimised for users. If a state appears and disappears within a single synchronous task (one "tick"), blocking the thread, the browser simply discards it to save resources. Efficient? Yes. Confusing? You bet.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR / The Takeaway 🎯
&lt;/h2&gt;

&lt;p&gt;Your mental model needs a shift:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt; controls &lt;strong&gt;STATE&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;The Browser&lt;/strong&gt; decides &lt;strong&gt;REALITY&lt;/strong&gt; (Rendering).&lt;/p&gt;

&lt;p&gt;The illusion breaks when we assume: "If the code ran, the user saw it." This is the curse that leads to "janky" interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next? ✨
&lt;/h2&gt;

&lt;p&gt;In the next part &lt;strong&gt;(Part 3)&lt;/strong&gt;, we are going to get properly under the hood. &lt;strong&gt;🧱 Call Stack 🧵 Main Thread ⏳ Synchronous Execution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ll break down exactly where JS lives, and why—before you can understand the Event Loop—you have to understand "The Queue."&lt;/p&gt;

&lt;h2&gt;
  
  
  💬 Question for the community:
&lt;/h2&gt;

&lt;p&gt;We have all accidentally "crashed" a browser tab with an accidental infinite loop or heavy recursion. What was the specific operation that first made you realize JS blocks the interface? Drop your stories (and failures) in the comments, let's laugh about it together! 👇&lt;/p&gt;

&lt;p&gt;Happy coding! 👩‍💻✨&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The Event Loop Is Not Magic — You Just Don’t Know the Spell ✨</title>
      <dc:creator>Elina Dzhelilova</dc:creator>
      <pubDate>Sat, 03 Jan 2026 19:06:10 +0000</pubDate>
      <link>https://forem.com/elina_web_magic/the-event-loop-is-not-magic-you-just-dont-know-the-spell-31fh</link>
      <guid>https://forem.com/elina_web_magic/the-event-loop-is-not-magic-you-just-dont-know-the-spell-31fh</guid>
      <description>&lt;p&gt;This part is mostly context and vibes. If you’re here for the technical stuff, skip straight to Part I 👇.&lt;br&gt;
I am a chronic ADHD person, and my brain absolutely refuses to learn complex systems the “normal” way. Long abstract explanations?&lt;br&gt;
Pls, kill me 😑🔫.&lt;br&gt;
Whitepapers? Nope 🥱.&lt;/p&gt;

&lt;p&gt;What does work for me is metaphors.&lt;br&gt;
And since I grew up obsessed with the &lt;strong&gt;Harry Potter&lt;/strong&gt; universe, my brain decided that spells, wands, and wizardry are the perfect way to understand how browsers and JavaScript actually work.&lt;/p&gt;

&lt;p&gt;Recently, I went way too deep into &lt;strong&gt;the Event Loop&lt;/strong&gt; 🔁, rendering, scheduling, and all the “why does this feel random” browser stuff. At some point, I realized I was basically building my own magical mental model just to survive.&lt;/p&gt;

&lt;p&gt;So… this series is me sharing that model.&lt;/p&gt;

&lt;p&gt;No “best practices” preaching 🙅‍♀️. Just a wizard trying to explain browser behavior in a way that finally made sense to her.&lt;/p&gt;

&lt;p&gt;If this helps you — awesome 🤘.&lt;/p&gt;

&lt;p&gt;If it doesn’t — totally fine 🤷‍♀️.&lt;/p&gt;

&lt;p&gt;If I got something wrong — please tell me (nicely 🥺🙏).&lt;/p&gt;

&lt;p&gt;And yes, there will be magical metaphors. A lot of them. 🧙‍♀️🔮&lt;/p&gt;

&lt;p&gt;Let’s go 🚀🪄&lt;/p&gt;

&lt;h2&gt;
  
  
  Part I: The Illusion 🔮
&lt;/h2&gt;

&lt;p&gt;Engineers often refer to it as “magic.”&lt;br&gt;&lt;br&gt;
Usually, we say this with a sigh of relief when a bug disappears without explanation.&lt;/p&gt;

&lt;p&gt;But let’s be honest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Magic only exists for those who don’t know the spell.&lt;/strong&gt; 🤫📜&lt;/p&gt;

&lt;p&gt;From a &lt;strong&gt;muggle’s&lt;/strong&gt; (user’s 🧑) point of view, the browser performs miracles.&lt;br&gt;&lt;br&gt;
From a &lt;strong&gt;wizard’s&lt;/strong&gt; (developer’s 🧙‍♀️) point of view, those miracles are the result of strict rules, queues, and constraints.&lt;/p&gt;

&lt;p&gt;This series is a map of that hidden machinery — not to make you memorize it, but to help you stop trusting the illusion.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Everything Looks Instant to Muggles 🐇
&lt;/h3&gt;

&lt;p&gt;From the muggles’ perspective, the interaction looks trivial.&lt;/p&gt;

&lt;p&gt;🖱️ Click → 🛒 Purchase → 🎉 Result&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2xcjjc5248ivp56lmr4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2xcjjc5248ivp56lmr4.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Chocolate Frog&lt;/em&gt; is already in the cart. The interface has been updated.&lt;/p&gt;

&lt;p&gt;No visible latency. No intermediate states. No sense that a complex mechanism has just executed under the hood. &lt;em&gt;(Or so we’d like to believe 🙃)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To muggles, this looks like &lt;strong&gt;magic&lt;/strong&gt; ✨.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faj6zbn7ro4yoqc6qbqss.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faj6zbn7ro4yoqc6qbqss.gif" alt=" " width="275" height="252"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Magic Is Engineered 🪄⚙️
&lt;/h2&gt;

&lt;p&gt;But this magic is not accidental. It is engineered 🏗️.&lt;/p&gt;

&lt;p&gt;Modern browsers intentionally hide complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event parsing&lt;/li&gt;
&lt;li&gt;State reconciliation&lt;/li&gt;
&lt;li&gt;Network handshakes&lt;/li&gt;
&lt;li&gt;Layout recalculation&lt;/li&gt;
&lt;li&gt;Paint and composite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hundreds of operations are collapsed into a single visual moment — roughly &lt;a href="https://web.dev/articles/rail" rel="noopener noreferrer"&gt;one frame (~16ms)&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Wizard’s Debt&lt;/strong&gt;. Here’s a fun fact no one usually tells you. You don’t actually get the full 16 milliseconds to run JavaScript. The browser takes its cut first — about &lt;strong&gt;6ms&lt;/strong&gt; for internal housekeeping (style, layout, paint). That leaves you ~&lt;strong&gt;10ms&lt;/strong&gt; to actually run your code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On a 60Hz display, 16.6ms is your whole world. On a 120Hz ProMotion screen, that budget drops to about &lt;strong&gt;8ms&lt;/strong&gt;. Miss the deadline — and the illusion shatters 💥&lt;/p&gt;




&lt;p&gt;Muggles do not perceive queues, scheduling, or thread blocking. They perceive continuity.&lt;/p&gt;

&lt;p&gt;That is why the illusion works.&lt;/p&gt;




&lt;h2&gt;
  
  
  When the Spell Breaks ⚡
&lt;/h2&gt;

&lt;p&gt;Problems begin when this illusion is treated as a contract.&lt;/p&gt;

&lt;p&gt;When it feels like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This line of code will definitely run after that one.&lt;/li&gt;
&lt;li&gt;A DOM change implies an immediate render. &lt;em&gt;(it should… well, not always 🌚)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;async&lt;/code&gt; guarantees non-blocking UI. &lt;em&gt;(spoiler: it doesn’t 😅)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Fast execution means correct execution. &lt;em&gt;(it works on my local machine 🙃)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These assumptions are intuitive. They are also the root cause of many production bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Reality Behind the Illusion 🎭
&lt;/h2&gt;

&lt;p&gt;From a wizard’s perspective 🧙‍♀️, there is no magic here — only constraints.&lt;/p&gt;

&lt;p&gt;What actually happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A muggle interaction placed an event into a queue 📥.&lt;/li&gt;
&lt;li&gt;JavaScript was executed when the main thread allowed it 🚦.&lt;/li&gt;
&lt;li&gt;A render may have happened — or may have been skipped due to optimization. JavaScript never promised timing ⏱️. &lt;em&gt;The browser never promised&lt;/em&gt; visual confirmation 🤝🚫. The illusion was merely held together.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The Event Loop feels “unpredictable” only when the illusion fails. &lt;em&gt;(And we all know exactly how that feels 🫠)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The UI freezes during scrolling.&lt;/li&gt;
&lt;li&gt;Animations fail to start.&lt;/li&gt;
&lt;li&gt;Promises resolve before the UI updates.&lt;/li&gt;
&lt;li&gt;Bugs appear only on low-end devices (the potato phones) or in background tabs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, the hidden machinery becomes visible.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;What muggles perceive as magic, wizards understand as a system of constraints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feh5xryr8u6c6yj8gbvfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feh5xryr8u6c6yj8gbvfs.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Real mastery begins when code is written &lt;strong&gt;with&lt;/strong&gt; these constraints in mind — not against them.&lt;br&gt;
Most bugs start with one silent assumption: that your code controls &lt;strong&gt;when&lt;/strong&gt; and &lt;strong&gt;in what order&lt;/strong&gt; the browser does things.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;In the next part, we’ll look at &lt;strong&gt;Who actually controls the Event Loop&lt;/strong&gt; ⚙️ — and why that assumption breaks real applications 💥&lt;/p&gt;

&lt;p&gt;Stay tuned 📩🔔👇.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Elina · WebMagic&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Mastering the Dark Arts of Web Development&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
