<?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>DEV Community: Mohammad Rajaei Monfared</title>
    <description>The latest articles on DEV Community by Mohammad Rajaei Monfared (@mrajaeim).</description>
    <link>https://dev.to/mrajaeim</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F697882%2F485e5eea-e5ff-4010-93c3-88634c92b475.png</url>
      <title>DEV Community: Mohammad Rajaei Monfared</title>
      <link>https://dev.to/mrajaeim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrajaeim"/>
    <language>en</language>
    <item>
      <title>Are AI-Generated Videos Rewriting Our Understanding of Physics?</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Sun, 26 Jul 2026 12:20:11 +0000</pubDate>
      <link>https://dev.to/mrajaeim/are-ai-generated-videos-rewriting-our-understanding-of-physics-32gc</link>
      <guid>https://dev.to/mrajaeim/are-ai-generated-videos-rewriting-our-understanding-of-physics-32gc</guid>
      <description>&lt;h2&gt;
  
  
  How synthetic reality may influence human intuition about motion, gravity, and causality
&lt;/h2&gt;

&lt;p&gt;AI video generation has reached a point where a model can create scenes that look physically convincing at first glance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A person jumping impossible distances&lt;/li&gt;
&lt;li&gt;Objects moving without inertia&lt;/li&gt;
&lt;li&gt;Water flowing upward&lt;/li&gt;
&lt;li&gt;Animals performing human-like actions&lt;/li&gt;
&lt;li&gt;Buildings bending like rubber&lt;/li&gt;
&lt;li&gt;People interacting with impossible environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For decades, humans learned physics by observing the real world.&lt;/p&gt;

&lt;p&gt;A ball falls.&lt;br&gt;
A glass breaks.&lt;br&gt;
A person cannot walk through a wall.&lt;br&gt;
Heavy objects require more force to move.&lt;/p&gt;

&lt;p&gt;These observations create what cognitive scientists call &lt;strong&gt;intuitive physics&lt;/strong&gt;: an internal mental model that predicts how objects should behave.&lt;/p&gt;

&lt;p&gt;But what happens when the majority of visual experiences become synthetic?&lt;/p&gt;

&lt;p&gt;Could AI-generated videos slowly change how future generations perceive reality?&lt;/p&gt;


&lt;h2&gt;
  
  
  Humans Do Not See Reality Directly
&lt;/h2&gt;

&lt;p&gt;A common misconception is that our brain works like a camera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reality → Eyes → Brain → Understanding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual process is closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reality
   ↓
Sensory input
   ↓
Brain prediction model
   ↓
Perception
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The brain is constantly predicting what should happen next.&lt;/p&gt;

&lt;p&gt;When you see a ball thrown into the air, your brain automatically predicts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trajectory&lt;/li&gt;
&lt;li&gt;speed&lt;/li&gt;
&lt;li&gt;gravity&lt;/li&gt;
&lt;li&gt;collision point&lt;/li&gt;
&lt;li&gt;acceleration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This happens before conscious reasoning.&lt;/p&gt;

&lt;p&gt;This capability is known as &lt;strong&gt;predictive processing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your brain is not only asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What am I seeing?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is also asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Does this match my internal model of how the world works?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Brain Learns Physics From Experience
&lt;/h2&gt;

&lt;p&gt;Young children do not learn physics from equations.&lt;/p&gt;

&lt;p&gt;They learn by interaction.&lt;/p&gt;

&lt;p&gt;A baby discovers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objects continue to exist when hidden&lt;/li&gt;
&lt;li&gt;Unsupported objects fall&lt;/li&gt;
&lt;li&gt;Solid objects cannot overlap&lt;/li&gt;
&lt;li&gt;Larger objects require more effort to move&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Researchers call these abilities &lt;strong&gt;core knowledge systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Humans appear to have an innate expectation that the physical world follows consistent rules.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;A child watching a ball roll behind a box expects it to continue moving.&lt;/p&gt;

&lt;p&gt;A child watching a video where a ball disappears and appears somewhere else recognizes something is unusual.&lt;/p&gt;

&lt;p&gt;The brain has a physics simulator.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Changes When Videos Become Physically Incorrect?
&lt;/h2&gt;

&lt;p&gt;Imagine a child growing up with thousands of hours of AI-generated videos.&lt;/p&gt;

&lt;p&gt;Many videos may contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;impossible acceleration&lt;/li&gt;
&lt;li&gt;incorrect gravity&lt;/li&gt;
&lt;li&gt;unrealistic collisions&lt;/li&gt;
&lt;li&gt;objects changing shape&lt;/li&gt;
&lt;li&gt;characters violating biomechanics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Does the brain update its physics model?&lt;/p&gt;

&lt;p&gt;The answer is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Probably yes, but not in a simple way.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The human brain is highly adaptable.&lt;/p&gt;

&lt;p&gt;It constantly adjusts based on experience.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pilots
&lt;/h3&gt;

&lt;p&gt;Pilots who use flight simulators develop new perceptual abilities.&lt;/p&gt;

&lt;p&gt;Their brains adapt to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unusual movement&lt;/li&gt;
&lt;li&gt;instrument-based navigation&lt;/li&gt;
&lt;li&gt;artificial visual environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gamers
&lt;/h3&gt;

&lt;p&gt;People who play first-person games become better at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;spatial reasoning&lt;/li&gt;
&lt;li&gt;predicting movement&lt;/li&gt;
&lt;li&gt;controlling virtual cameras&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The brain can learn artificial environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  But There Is an Important Difference
&lt;/h2&gt;

&lt;p&gt;Games and simulations usually have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;consistent fake physics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI-generated videos may have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inconsistent fake physics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This difference matters.&lt;/p&gt;

&lt;p&gt;A game creates a new rule system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;World&lt;/span&gt; &lt;span class="py"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="py"&gt;Gravity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;9.8 m/s²&lt;/span&gt;
&lt;span class="py"&gt;Collision&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;consistent&lt;/span&gt;
&lt;span class="py"&gt;Movement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;predictable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your brain learns:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This world has different rules."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But AI-generated videos may show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Video 1:
Gravity exists

Video 2:
Gravity disappears

Video 3:
Objects move backward in time

Video 4:
Humans stretch like cartoons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is not artificial reality.&lt;/p&gt;

&lt;p&gt;The problem is unstable reality.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Same Question Was Asked About Cartoons
&lt;/h2&gt;

&lt;p&gt;This is not the first time humans have worried about artificial representations.&lt;/p&gt;

&lt;p&gt;Cartoons have shown impossible physics for more than a century.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Characters surviving explosions&lt;/li&gt;
&lt;li&gt;Objects stretching&lt;/li&gt;
&lt;li&gt;Gravity stopping until someone notices&lt;/li&gt;
&lt;li&gt;Characters falling after realizing they are in the air&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yet most people do not believe these things happen.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because humans categorize information.&lt;/p&gt;

&lt;p&gt;The brain understands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cartoon world ≠ Real world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The concern with AI-generated video is different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI video ≈ Real video
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The boundary becomes less obvious.&lt;/p&gt;




&lt;h2&gt;
  
  
  The New Problem: Loss of Reality Labels
&lt;/h2&gt;

&lt;p&gt;Historically, humans had strong signals:&lt;/p&gt;

&lt;p&gt;Real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;camera imperfections&lt;/li&gt;
&lt;li&gt;physical limitations&lt;/li&gt;
&lt;li&gt;consistent lighting&lt;/li&gt;
&lt;li&gt;natural motion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fake:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;animation style&lt;/li&gt;
&lt;li&gt;obvious CGI&lt;/li&gt;
&lt;li&gt;unrealistic rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern AI video reduces this gap.&lt;/p&gt;

&lt;p&gt;A generated video may look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Real camera
+
Real person
+
Real environment
+
Impossible physics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The viewer receives conflicting information:&lt;/p&gt;

&lt;p&gt;Visual realism says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This happened."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Physics intuition says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This cannot happen."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Could This Affect Future Generations?
&lt;/h2&gt;

&lt;p&gt;A realistic scenario:&lt;/p&gt;

&lt;p&gt;A child sees thousands of AI-generated videos before having enough real-world experience.&lt;/p&gt;

&lt;p&gt;Their visual dataset becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Internet videos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;70% synthetic&lt;/span&gt;
    &lt;span class="s"&gt;30% real&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Their brain learns statistical patterns from this environment.&lt;/p&gt;

&lt;p&gt;Modern AI systems work similarly.&lt;/p&gt;

&lt;p&gt;A neural network learns from data distribution.&lt;/p&gt;

&lt;p&gt;Humans also learn from experience distribution.&lt;/p&gt;

&lt;p&gt;However, humans have additional sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;physical interaction&lt;/li&gt;
&lt;li&gt;social correction&lt;/li&gt;
&lt;li&gt;scientific education&lt;/li&gt;
&lt;li&gt;personal experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Touching a falling object is stronger evidence than watching 10,000 videos.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Risk Is Not Physics — It Is Trust
&lt;/h2&gt;

&lt;p&gt;The most significant cognitive impact may not be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"People believe impossible physics."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It may be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"People stop knowing what evidence to trust."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AI-generated videos challenge our assumption:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Seeing = knowing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For thousands of years:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I saw it happen" was strong evidence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I saw a video" is no longer enough.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;journalism&lt;/li&gt;
&lt;li&gt;education&lt;/li&gt;
&lt;li&gt;scientific communication&lt;/li&gt;
&lt;li&gt;politics&lt;/li&gt;
&lt;li&gt;social trust&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Implications for Software Engineers Building AI Systems
&lt;/h2&gt;

&lt;p&gt;As developers building generative AI products, we should think beyond model quality.&lt;/p&gt;

&lt;p&gt;The question is not only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can we generate realistic video?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The bigger question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How will humans interpret these generated realities?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Possible engineering solutions:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Provenance Metadata
&lt;/h3&gt;

&lt;p&gt;Generated content should carry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;source:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AI-generated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;model:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"video-model-x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;timestamp:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;generation_id:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to image metadata standards.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Watermarking
&lt;/h3&gt;

&lt;p&gt;Invisible signals could help detect synthetic media.&lt;/p&gt;

&lt;p&gt;Challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;attackers may remove them&lt;/li&gt;
&lt;li&gt;compression can damage them&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Physics-Aware Generation
&lt;/h3&gt;

&lt;p&gt;Future video models may need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Visual realism
+
Physical simulation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of only learning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What pixels usually look like"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;they need:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How the world behaves."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Possible integration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Video Model

        +

Physics Engine

        +

World Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Future: Synthetic Reality Needs Synthetic Literacy
&lt;/h2&gt;

&lt;p&gt;The next generation may not have a problem distinguishing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;real vs cartoon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They will need to distinguish:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;real event
generated event
simulated event
edited event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just as previous generations learned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;books are not reality
movies are not reality
games are not reality
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;future generations must learn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI video is not automatically evidence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;AI-generated videos probably will not make humans forget basic physics.&lt;/p&gt;

&lt;p&gt;Our brains are too strongly grounded in physical interaction.&lt;/p&gt;

&lt;p&gt;However, synthetic media may change something deeper:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;our relationship with visual evidence.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The challenge of the AI era is not only creating machines that can generate realities.&lt;/p&gt;

&lt;p&gt;It is creating humans who can navigate a world where reality itself can be generated.&lt;/p&gt;

&lt;p&gt;The future skill may not be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can you create realistic images?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It may be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can you reason about reality when images are no longer reliable?"&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>chatgpt</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>How I Refactored a Distributed Hardware Control System into a Reusable Framework</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Sat, 25 Jul 2026 13:55:41 +0000</pubDate>
      <link>https://dev.to/mrajaeim/how-i-refactored-a-distributed-hardware-control-system-into-a-reusable-framework-12cg</link>
      <guid>https://dev.to/mrajaeim/how-i-refactored-a-distributed-hardware-control-system-into-a-reusable-framework-12cg</guid>
      <description>&lt;p&gt;Building software for industrial machines taught me an unexpected lesson: scaling isn't about adding more hardware, it's about reducing architectural complexity.&lt;/p&gt;

&lt;p&gt;A few years ago, I led the development of a distributed hardware control system that orchestrated multiple industrial machines. The master controller coordinated production, while a React dashboard gave operators real-time visibility through WebSockets. Under the hood, we were running a fleet of Raspberry Pis, each communicating with an Arduino Due running the g2core motion control firmware.&lt;/p&gt;

&lt;p&gt;At first, everything seemed straightforward. But as we added more robotic cells, our software began to buckle under the weight of its own abstractions.&lt;/p&gt;

&lt;p&gt;This is the story of how a simple collection of control scripts morphed into an overly generic, bloated framework, and how I eventually had to tear it all down to build a clean, domain-driven architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Day Scripts Stopped Scaling
&lt;/h2&gt;

&lt;p&gt;When you are controlling physical motors, early success is intoxicating. You send a JSON payload over TCP, a stepper motor whirs to life, and a robotic arm moves exactly 150 millimeters to the right.&lt;/p&gt;

&lt;p&gt;But distributed systems have a funny way of punishing organic growth. As we expanded the production line by adding six more robotic cells, bringing the system to around sixteen distributed nodes, the software architecture began showing its limits. We experienced dropped TCP connections, skipped heartbeats, and UI state that desynced from the physical hardware.&lt;/p&gt;

&lt;p&gt;The real challenge wasn't controlling motors anymore. It was controlling complexity.&lt;/p&gt;

&lt;p&gt;To understand why the system started fighting us, you first have to understand the hardware stack we were building on.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understanding the Hardware Stack
&lt;/h2&gt;

&lt;p&gt;Industrial environments require strict separation of concerns between high-level orchestration and low-level real-time execution. Our stack looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HMI (Human-Machine Interface):&lt;/strong&gt; A React frontend communicating via WebSockets for real-time monitoring and HTTP for configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Master Controller:&lt;/strong&gt; An asynchronous Python application orchestrating the entire factory floor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Raspberry Pi (Slave):&lt;/strong&gt; A local edge computer for each machine, running a Python TCP server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arduino Due:&lt;/strong&gt; The real-time microcontroller running &lt;strong&gt;g2core&lt;/strong&gt;, translating high-level JSON/G-code into precise electrical pulses for the motor drivers.&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbrbmixjdixurr150vjq9.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbrbmixjdixurr150vjq9.jpg" alt="Robotic System Stack" width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This hardware separation is standard. The architectural problem was how we mapped our software onto it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The First Design: Simple, But Naive
&lt;/h2&gt;

&lt;p&gt;For the first version of the system, we kept the slave software intentionally dumb. The Raspberry Pi exposed a TCP server, accepted JSON commands, forwarded them to g2core over a serial port, and returned the results.&lt;/p&gt;

&lt;p&gt;It looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Early design: Networking, request routing, and hardware control
# all live inside a single class.
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DeviceServer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Open a direct serial connection to the Arduino/g2core firmware.
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;115200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Simple command router: map incoming JSON commands
&lt;/span&gt;        &lt;span class="c1"&gt;# to Python handler functions.
&lt;/span&gt;        &lt;span class="c1"&gt;#
&lt;/span&gt;        &lt;span class="c1"&gt;# This worked well initially, but as more commands and
&lt;/span&gt;        &lt;span class="c1"&gt;# workflows were added, this dictionary became the center
&lt;/span&gt;        &lt;span class="c1"&gt;# of the entire application.
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMMAND_HANDLER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;raw&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_handle_raw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;G1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_handle_move&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_handle_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Receive a JSON request from a TCP client.
&lt;/span&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="c1"&gt;# Find the corresponding command handler.
&lt;/span&gt;        &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMMAND_HANDLER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Execute business logic, which often communicates
&lt;/span&gt;            &lt;span class="c1"&gt;# with the Arduino over the serial port.
&lt;/span&gt;            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payload&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

            &lt;span class="c1"&gt;# Send the result back to the client.
&lt;/span&gt;            &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_send_serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Send a command to the Arduino/g2core controller.
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="c1"&gt;# ⚠️ Problem:
&lt;/span&gt;        &lt;span class="c1"&gt;# This blocks until the Arduino responds.
&lt;/span&gt;        &lt;span class="c1"&gt;#
&lt;/span&gt;        &lt;span class="c1"&gt;# Although the server uses asyncio, every command that
&lt;/span&gt;        &lt;span class="c1"&gt;# waits here prevents this request from making progress.
&lt;/span&gt;        &lt;span class="c1"&gt;# As more machines and longer-running operations were added,
&lt;/span&gt;        &lt;span class="c1"&gt;# serial communication became a scalability bottleneck.
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Original Request Flow
&lt;/h3&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1w9rifec6fia6qhr6xip.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1w9rifec6fia6qhr6xip.png" alt="Simple flow of Robotic System" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simple. Easy to understand. Easy to debug. For one machine, it was exactly the right architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Architectural Smells
&lt;/h2&gt;

&lt;p&gt;As the system grew, this simple script became a nightmare. We encountered problems that every distributed system eventually faces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Blocking I/O Killed Concurrency:&lt;/strong&gt; Look at &lt;code&gt;_send_serial&lt;/code&gt; in the snippet above. It calls &lt;code&gt;ser.readline()&lt;/code&gt;. Because serial communication is slow, this blocked the entire asynchronous event loop. While the Pi waited for the Arduino to confirm a motor move, it couldn't respond to network heartbeats. The Master Controller assumed the Pi was dead and initiated a fault recovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Lived Everywhere:&lt;/strong&gt; If an operator pressed "Pause" on the HMI, where did that state live? The Controller had a &lt;code&gt;is_paused&lt;/code&gt; flag. The Pi TCP server had a &lt;code&gt;state = PAUSED&lt;/code&gt; variable. The Arduino &lt;em&gt;also&lt;/em&gt; had its own internal motion planner state. Keeping these three in sync across unreliable TCP connections resulted in massive race conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow Leaked into Infrastructure:&lt;/strong&gt; We started adding retry logic, pause/resume handling, and fault recovery directly inside the socket handlers. Our networking code was suddenly making business decisions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  5. The Wrong Refactor: Abstract Everything
&lt;/h2&gt;

&lt;p&gt;Like many engineers facing a messy codebase, my instinct was to extract every recurring pattern into its own module. I decided to build a "Hardware Control Framework."&lt;/p&gt;

&lt;p&gt;The directory structure gradually looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;framework/
├── cycles/        # Lifecycle managers
├── events/        # Global event bus (Pub/Sub)
├── hardware/      # Base classes for hardware
├── mixins/        # StateMachineMixin, RetryMixin, etc.
├── network/       # Abstracted TCP/UDP logic
├── serial/        # Serial communication wrappers
└── system/        # Global singletons

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, this looked like progress. Everything was abstract. Everything was reusable.&lt;/p&gt;

&lt;p&gt;But I had fallen into a classic trap: &lt;strong&gt;The framework had started solving problems that didn't actually exist.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw0jezokjr0siekigq4dx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw0jezokjr0siekigq4dx.png" alt="The Wrong Refactor Abstract Everything" width="799" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had heavily utilized mixins and deep inheritance. A single &lt;code&gt;RoboticArm&lt;/code&gt; class inherited from &lt;code&gt;HardwareBase&lt;/code&gt;, &lt;code&gt;StateMachineMixin&lt;/code&gt;, and &lt;code&gt;NetworkNode&lt;/code&gt;. When a TCP packet failed to send, the stack trace hopped through 15 different abstract files.&lt;/p&gt;

&lt;p&gt;Some abstractions represented real domain concepts. Others existed simply because I &lt;em&gt;could&lt;/em&gt; create them. They made the framework larger without making the architecture clearer.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Designing the Architecture I'd Build Today
&lt;/h2&gt;

&lt;p&gt;Looking back, I realized the project contained three completely different kinds of software:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure:&lt;/strong&gt; TCP sockets, connection pooling, heartbeats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device Runtime:&lt;/strong&gt; Serial communication, g2core protocols, hardware limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production Logic:&lt;/strong&gt; Recipes, machine coordination, calibration steps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If I were starting over, I would abandon the "general-purpose framework" approach and strictly organize the software around &lt;strong&gt;domain responsibilities&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Refactored Architecture
&lt;/h3&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F63xrjktmbsn1oebt01de.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F63xrjktmbsn1oebt01de.png" alt="DDD Architecture for Robotic System" width="800" height="2642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is why each component exists and the specific problems it solves:&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the Controller Exists
&lt;/h3&gt;

&lt;p&gt;The controller orchestrates the system. It starts production scripts, manages the lifecycle, and enforces that only one production workflow runs at a time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem it Solves:&lt;/strong&gt; Without it, workflow ownership is unclear, and pause/resume logic spreads across the codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Constraint:&lt;/strong&gt; It doesn't know anything about serial ports, motor drivers, or sockets. It coordinates. Nothing more.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why the Machine Agent Exists
&lt;/h3&gt;

&lt;p&gt;Each physical machine becomes an object with ownership over its own state &lt;em&gt;on the master server&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem it Solves:&lt;/strong&gt; Instead of scattering networking code throughout the application, the &lt;code&gt;MachineAgent&lt;/code&gt; owns the TCP client, the status cache, and high-level operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Result:&lt;/strong&gt; The caller never thinks about sockets or retries. Production scripts just call &lt;code&gt;machine.rotate(10)&lt;/code&gt; or &lt;code&gt;machine.home()&lt;/code&gt;. The agent encapsulates the network complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why the Job Queue Exists (The Game Changer)
&lt;/h3&gt;

&lt;p&gt;Industrial machines require deterministic execution. Motion commands cannot execute concurrently just because they're asynchronous in software. If you send a "Move X" and "Move Y" command at the same time, the hardware might attempt to interpolate them, crash, or ignore one entirely.&lt;/p&gt;

&lt;p&gt;Each edge device now owns a strict, sequential Job Queue.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7tfzjds5vmm4v0zk0fz4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7tfzjds5vmm4v0zk0fz4.png" alt="edge device now owns a strict, sequential Job Queue" width="800" height="2069"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This simple rule removed an entire class of race conditions. Concurrency is handled by the transport layer (so heartbeats can still be processed), but hardware execution is strictly sequential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the Transport Layer is Isolated
&lt;/h3&gt;

&lt;p&gt;Communication deserves its own module. Nothing more. Nothing less. It handles request/response tracking, the JSON protocol, connection pooling, and fault recovery. It is &lt;em&gt;not&lt;/em&gt; a service discovery framework, and it does not know what a "motor" is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Recipes are Separated from Workflows
&lt;/h3&gt;

&lt;p&gt;In the old system, scripts contained hardcoded values. In the new architecture, &lt;strong&gt;Recipes are configuration, and Scripts are execution.&lt;/strong&gt; A recipe stores parameters (e.g., &lt;code&gt;target_temperature = 200&lt;/code&gt;, &lt;code&gt;feed_rate = 50&lt;/code&gt;). Production scripts decide &lt;em&gt;how&lt;/em&gt; to use them. Keeping data and logic separate makes both trivially easy to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Why This Design Scales Better
&lt;/h2&gt;

&lt;p&gt;This domain-driven approach fundamentally changed the stability of our system.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fault Isolation:&lt;/strong&gt; When a serial cable was unplugged, the Device Runtime threw an error. The Job Queue paused. The Transport layer cleanly reported the error back to the Machine Agent. The Controller saw the error and halted the workflow. No hanging sockets, no deadlocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No More God Objects:&lt;/strong&gt; By favoring composition over inheritance, we deleted all our &lt;code&gt;Mixins&lt;/code&gt;. A Machine doesn't &lt;em&gt;inherit&lt;/em&gt; from a NetworkNode; a Machine &lt;em&gt;has&lt;/em&gt; a NetworkNode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;True Asynchronous I/O:&lt;/strong&gt; By separating the network transport from the hardware execution queue, the Pi could instantly respond to a "status check" or "heartbeat" over TCP, even if the motors were in the middle of a 30-second physical movement.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. Lessons Learned: Design Principles I Follow Today
&lt;/h2&gt;

&lt;p&gt;When engineers hear the word "framework," it's tempting to think about flexibility and abstraction. But experience has taught me that frameworks should emerge from domain concepts, not from implementation details.&lt;/p&gt;

&lt;p&gt;If I were starting this system over today, I would follow these seven rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Master orchestrates; the Slave executes.&lt;/strong&gt; Never put business logic on the edge device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scripts describe workflows; recipes hold data.&lt;/strong&gt; Don't hardcode production logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machines own their own state and queues.&lt;/strong&gt; Protect your hardware with strict, sequential execution queues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer composition over deep inheritance or mixins.&lt;/strong&gt; Avoid the trap of the "clever" object-oriented hierarchy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create new modules only when a second real use case appears.&lt;/strong&gt; Don't preemptively abstract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wire dependencies explicitly at startup&lt;/strong&gt; instead of relying on global singletons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep infrastructure invisible to business logic&lt;/strong&gt; whenever possible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These principles aren't specific to robotics or mechatronics. You could replace the Arduino with a cloud database, the stepper motors with background worker tasks, and the Raspberry Pi with a microservice. The architectural boundaries remain exactly the same.&lt;/p&gt;

&lt;p&gt;The most valuable part of this project wasn't writing code that controlled motors. It was learning to separate orchestration, communication, and device control. Ironically, the final architecture contained fewer modules than my original "framework", yet it explained the system much more clearly.&lt;/p&gt;

&lt;p&gt;Sometimes the best refactoring isn't adding another abstraction. It's deleting one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'd love to hear how you've approached similar problems. Have you ever built a framework that later became too generic? Or simplified an architecture by removing abstractions instead of adding them? Let's discuss it in the comments below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>architecture</category>
      <category>software</category>
    </item>
    <item>
      <title>Advanced JS Execution: Promises, Workers, and Comlink</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Wed, 22 Jul 2026 13:52:41 +0000</pubDate>
      <link>https://dev.to/mrajaeim/advanced-js-execution-promises-workers-and-comlink-ill</link>
      <guid>https://dev.to/mrajaeim/advanced-js-execution-promises-workers-and-comlink-ill</guid>
      <description>&lt;p&gt;You wrap a slow loop in an &lt;code&gt;async&lt;/code&gt; function. You sprinkle in &lt;code&gt;await&lt;/code&gt;. You tell yourself the page will stay smooth because the work is "async now."&lt;/p&gt;

&lt;p&gt;Then you click the button.&lt;/p&gt;

&lt;p&gt;The tab locks. Scroll dies. The spinner never spins. Clicks pile up like unanswered mail. Thirty seconds later, the status finally says "Done" — and you wonder whether Promises are broken.&lt;/p&gt;

&lt;p&gt;They are not. You asked them to solve a problem they were never designed for.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Promises help you wait.&lt;/strong&gt; They do not move CPU work off the main thread. &lt;strong&gt;Web Workers&lt;/strong&gt; do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That distinction is the whole article. We will build it in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why &lt;code&gt;async&lt;/code&gt; can still freeze the UI&lt;/li&gt;
&lt;li&gt;How a worker fixes it with &lt;code&gt;postMessage&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;How Comlink, SharedArrayBuffer, and pools fit when the app grows up&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One example carries us through: crunch a large array of numbers (pixels, analytics rows, whatever) without locking the page.&lt;/p&gt;

&lt;p&gt;If you want the foundation first — call stack, microtasks vs macrotasks, and the event loop — start with my earlier post: &lt;a href="https://dev.to/mrajaeim/why-your-javascript-runs-in-the-wrong-order-2fki"&gt;Why Your JavaScript Runs in the Wrong Order&lt;/a&gt;. This article picks up where that one leaves off: when waiting is not enough and you need another thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Runnable examples
&lt;/h3&gt;

&lt;p&gt;Every major step has a small project you can clone and run. They live in &lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples" rel="noopener noreferrer"&gt;&lt;code&gt;examples/&lt;/code&gt;&lt;/a&gt;. The repo &lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/blob/main/README.md" rel="noopener noreferrer"&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/a&gt; has install commands.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Folder&lt;/th&gt;
&lt;th&gt;What you learn&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frozen UI&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/01-main-thread-freeze" rel="noopener noreferrer"&gt;&lt;code&gt;01-main-thread-freeze&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;async&lt;/code&gt; + heavy loop still blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raw worker&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/02-raw-web-worker" rel="noopener noreferrer"&gt;&lt;code&gt;02-raw-web-worker&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;postMessage&lt;/code&gt; keeps UI responsive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comlink&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/03-comlink-worker" rel="noopener noreferrer"&gt;&lt;code&gt;03-comlink-worker&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Call the worker like &lt;code&gt;await api.calculate(length)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared memory&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/04-shared-array-buffer" rel="noopener noreferrer"&gt;&lt;code&gt;04-shared-array-buffer&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Comlink + SharedArrayBuffer + COOP/COEP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser pool&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/05-workerpool" rel="noopener noreferrer"&gt;&lt;code&gt;05-workerpool&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Queue many jobs across workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node pool&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/06-piscina-node" rel="noopener noreferrer"&gt;&lt;code&gt;06-piscina-node&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Piscina on Node &lt;code&gt;worker_threads&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/mrajaeim/Advanced-JS-Execution.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Advanced-JS-Execution/examples/02-raw-web-worker
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The snippets below are shortened for reading. Prefer the GitHub projects when you want the full UI — status text, a Ping button that shows click counts on its label, and Vite setup included.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Most of us learn a comforting story about async JavaScript:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the code uses &lt;code&gt;async&lt;/code&gt; / &lt;code&gt;await&lt;/code&gt; / Promises, the UI stays smooth.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That story is half true. It holds when you are &lt;strong&gt;waiting&lt;/strong&gt; — for a network response, a timer, a disk read. It falls apart the moment you start &lt;strong&gt;computing&lt;/strong&gt; on the main thread.&lt;/p&gt;

&lt;p&gt;Here is the trap in miniature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processOnMainThread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// yields once, then...&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ...this still owns the main thread&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Working...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;processOnMainThread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Done: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you expect: the status updates, the page stays clickable, then "Done" appears.&lt;/p&gt;

&lt;p&gt;What you get: a frozen tab until the loop finishes.&lt;/p&gt;

&lt;p&gt;Open &lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/01-main-thread-freeze" rel="noopener noreferrer"&gt;&lt;code&gt;examples/01-main-thread-freeze&lt;/code&gt;&lt;/a&gt;, click &lt;strong&gt;Run heavy work&lt;/strong&gt;, dismiss the alert, then try &lt;strong&gt;Ping UI&lt;/strong&gt; or change the array length. The Ping button label (&lt;code&gt;Ping UI (1)&lt;/code&gt;, &lt;code&gt;Ping UI (2)&lt;/code&gt;, …) should stall — and so should the input. That is the main thread, busy doing math, unable to paint or handle input.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;await Promise.resolve()&lt;/code&gt; only delayed the freeze by one microtask. The math never left the main thread. You scheduled a wait — then immediately monopolized the only thread the UI has.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why It Happens
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Promises resume on the same thread
&lt;/h3&gt;

&lt;p&gt;A Promise is a promise of a value &lt;em&gt;later&lt;/em&gt;. When it settles, &lt;code&gt;.then&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; continue as microtasks on the &lt;strong&gt;same main thread&lt;/strong&gt; that started them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAIN THREAD
sync code → await (wait for I/O) → more sync code HERE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That shape is perfect for &lt;code&gt;fetch&lt;/code&gt;. It is a disaster for a multi-second CPU loop, because the loop is not waiting for anything. It is work. And work on the main thread means the browser cannot reliably handle clicks, DOM updates, or smooth animation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The main thread has one call stack
&lt;/h3&gt;

&lt;p&gt;While that stack is chewing through tens of millions of iterations, nothing else gets a turn. The UI is not "slow." It is parked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workers are a second JavaScript thread
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Web Worker&lt;/strong&gt; has its own call stack and its own event loop. It cannot touch the DOM — that is the trade. In exchange, it can grind through heavy work while the main thread stays free for people clicking buttons.&lt;/p&gt;

&lt;p&gt;You talk with messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAIN THREAD                         WORKER THREAD
UI, DOM, clicks                     heavy CPU work
     │ postMessage(data)                  │
     └──────────────────────────────────► │
     │                                    │ compute
     │ ◄──────────────────────────────────┘
       onmessage(result)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Where the loop runs&lt;/th&gt;
&lt;th&gt;UI during work&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;await&lt;/code&gt; + loop on main&lt;/td&gt;
&lt;td&gt;Main call stack&lt;/td&gt;
&lt;td&gt;Frozen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worker + &lt;code&gt;postMessage&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Worker call stack&lt;/td&gt;
&lt;td&gt;Responsive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here is the part that confuses people: the main thread can still use a Promise to &lt;strong&gt;wait for the worker's reply&lt;/strong&gt;. That Promise is waiting for a message. The heavy work already ran somewhere else. Same &lt;code&gt;await&lt;/code&gt; keyword. Completely different place the CPU spent its time.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Confirm It (Before You Fix It)
&lt;/h2&gt;

&lt;p&gt;Before you reach for a worker, ask of each line: is this waiting, or is this computing?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// WAIT (cheap)&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;        &lt;span class="c1"&gt;// COMPUTE on main (expensive)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the expensive part is compute, another Promise will not save you. You need another thread.&lt;/p&gt;

&lt;p&gt;In Chrome DevTools &lt;strong&gt;Performance&lt;/strong&gt;, record a click. Look for a long yellow main-thread task that lines up with your loop. That block is the smoking gun — and the reason your spinner never moved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Better Solution: Move the Loop to a Worker
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Use a Promise for waiting. Use a Web Worker for heavy computing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The pattern is simple once you say it out loud:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep UI on the main thread&lt;/li&gt;
&lt;li&gt;Put the heavy work in &lt;code&gt;worker.js&lt;/code&gt; — including building the big array&lt;/li&gt;
&lt;li&gt;Send only what you need with &lt;code&gt;postMessage&lt;/code&gt; (here: the length)&lt;/li&gt;
&lt;li&gt;Wrap the reply in a Promise so UI code can still &lt;code&gt;await&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Full runnable app: &lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/02-raw-web-worker" rel="noopener noreferrer"&gt;&lt;code&gt;examples/02-raw-web-worker&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;worker.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;main.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processInWorker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onerror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Working...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;processInWorker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Done: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the expected behavior matches reality: "Working..." stays visible, &lt;strong&gt;Ping UI&lt;/strong&gt; keeps updating its label (&lt;code&gt;Ping UI (1)&lt;/code&gt;, &lt;code&gt;Ping UI (2)&lt;/code&gt;, …), and "Done" appears when the worker finishes. The &lt;code&gt;await&lt;/code&gt; is still there — but it is waiting for a message, not for the main thread to finish math.&lt;/p&gt;

&lt;h3&gt;
  
  
  What each piece does
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;new Worker(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Starts a second JS thread (no DOM access)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;postMessage(length)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sends a small number; main continues immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worker's &lt;code&gt;onmessage&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Builds the array and runs the loop on the worker stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;processInWorker&lt;/code&gt;'s Promise&lt;/td&gt;
&lt;td&gt;Only waits for the reply — does not run the math&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAIN                                   WORKER
click → status = "Working..."
postMessage(length) ────────────────► receive length
await (main free for clicks)            build array + run loop
onmessage ←────────────────────────── postMessage(total)
status = "Done..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; soften small freezes by chunking a loop with &lt;code&gt;setTimeout(0)&lt;/code&gt; on the main thread. For large jobs it gets messy fast — progress, cancellation, slower total time, harder reasoning. A worker is the clearer architecture: one place for UI, one place for grind.&lt;/p&gt;




&lt;h2&gt;
  
  
  Next Step: Comlink (RPC-style Workers)
&lt;/h2&gt;

&lt;p&gt;Raw &lt;code&gt;postMessage&lt;/code&gt; is honest and a little painful. As soon as the worker has more than one job, you invent a protocol: message types, payloads, request IDs, error shapes. You become a courier for your own functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/GoogleChromeLabs/comlink" rel="noopener noreferrer"&gt;Comlink&lt;/a&gt;&lt;/strong&gt; is a thin RPC layer on top of workers. The idea is almost embarrassingly simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The worker &lt;strong&gt;exposes&lt;/strong&gt; an API object&lt;/li&gt;
&lt;li&gt;The main thread &lt;strong&gt;wraps&lt;/strong&gt; the worker&lt;/li&gt;
&lt;li&gt;You call &lt;code&gt;await api.calculate(length)&lt;/code&gt; like a normal async module&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Under the hood it still uses messages. The mental model does not change: wait with Promises, compute on a worker. Comlink just stops you from hand-writing the routing.&lt;/p&gt;

&lt;p&gt;Runnable project: &lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/03-comlink-worker" rel="noopener noreferrer"&gt;&lt;code&gt;examples/03-comlink-worker&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worker&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expose&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comlink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;calculate&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Main&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;wrap&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comlink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Style&lt;/th&gt;
&lt;th&gt;Call site&lt;/th&gt;
&lt;th&gt;Who routes replies&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raw &lt;code&gt;postMessage&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ type, payload }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comlink&lt;/td&gt;
&lt;td&gt;&lt;code&gt;await api.calculate(length)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Comlink&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use raw messaging for one tiny job with zero dependencies. Reach for Comlink when the worker becomes a real API — image pipelines, inference helpers, multi-method tools. Comlink also supports transferables, typed APIs, and SharedArrayBuffer-friendly flows when you need them later.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Copying Data Is the Bottleneck: SharedArrayBuffer
&lt;/h2&gt;

&lt;p&gt;Sometimes the math is fine, and the tax is the copy. &lt;code&gt;postMessage&lt;/code&gt; clones or transfers data. For huge frames or tensors shared by several workers, that traffic can dominate cost — you spend more time moving memory than processing it.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;SharedArrayBuffer&lt;/strong&gt; is memory more than one thread can see at once. Workers mutate it in place. You still need careful partitioning or Atomics so threads do not corrupt each other. Shared memory without a race strategy is just a faster way to get weird bugs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Main (UI)
   │ Comlink (start job / progress / done)
Worker pool
   │ SharedArrayBuffer (pixels, tensors)
WASM / SIMD kernels
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Runnable project (Vite already sets COOP/COEP): &lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/04-shared-array-buffer" rel="noopener noreferrer"&gt;&lt;code&gt;examples/04-shared-array-buffer&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SharedArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Float32Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BYTES_PER_ELEMENT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Workers fill and mutate their slices; main only allocates.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;processShared&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you adopt it, you need three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cross-origin isolation headers (&lt;code&gt;COOP: same-origin&lt;/code&gt;, &lt;code&gt;COEP: require-corp&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A race strategy (split ranges, single writer, or Atomics)&lt;/li&gt;
&lt;li&gt;Proof from profiling that cloning or transfer is actually the problem&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Start with Comlink + normal messages or transferables. Add SharedArrayBuffer when memory movement — not the algorithm — is the cost.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Pools: Many Jobs, Not One Worker Per Click
&lt;/h2&gt;

&lt;p&gt;Creating a worker has startup cost. Spawning a fresh one on every click is like hiring a new employee for every email. If the UI fires many jobs, use a pool: a small set of workers that share a queue.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browser job queue&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/josdejong/workerpool" rel="noopener noreferrer"&gt;workerpool&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/05-workerpool" rel="noopener noreferrer"&gt;&lt;code&gt;examples/05-workerpool&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node &lt;code&gt;worker_threads&lt;/code&gt; pool&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/piscinajs/piscina" rel="noopener noreferrer"&gt;Piscina&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/06-piscina-node" rel="noopener noreferrer"&gt;&lt;code&gt;examples/06-piscina-node&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Browser (workerpool):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;workerpool&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;workerpool&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workerpool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./heavy.worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calculate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jobId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Node (Piscina):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Piscina&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;piscina&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Piscina&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jobId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pick a stack by scenario
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;React / Vite UI, readable worker API&lt;/td&gt;
&lt;td&gt;Comlink (+ workerpool if many jobs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser AI / vision / big frames&lt;/td&gt;
&lt;td&gt;Comlink or workerpool + WASM/ONNX, SharedArrayBuffer if needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node images, PDFs, compression, ML&lt;/td&gt;
&lt;td&gt;Piscina&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A quick map of the libraries (numbers and APIs change over time):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Best at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/GoogleChromeLabs/comlink" rel="noopener noreferrer"&gt;Comlink&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;await worker.method()&lt;/code&gt; ergonomics in the browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/josdejong/workerpool" rel="noopener noreferrer"&gt;workerpool&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Queue + N workers (browser or Node)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/piscinajs/piscina" rel="noopener noreferrer"&gt;Piscina&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Production Node worker pool&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Warnings Worth Knowing
&lt;/h2&gt;

&lt;p&gt;A few sharp edges show up again and again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No DOM in workers.&lt;/strong&gt; Compute there. Update React or the DOM on the main thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Huge clones stall the main thread too.&lt;/strong&gt; Prefer transferables for big &lt;code&gt;ArrayBuffer&lt;/code&gt;s: &lt;code&gt;worker.postMessage(buffer, [buffer])&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Match worker type to how you load it&lt;/strong&gt; (&lt;code&gt;classic&lt;/code&gt; vs &lt;code&gt;{ type: 'module' }&lt;/code&gt;). A mismatch fails in ways that look mysterious at first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wire &lt;code&gt;worker.onerror&lt;/code&gt;&lt;/strong&gt; (and pool errors). Without that, failures look like hung Promises that never settle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser Workers ≠ Node &lt;code&gt;worker_threads&lt;/code&gt;.&lt;/strong&gt; Same idea, different APIs and libraries. Do not paste one into the other and expect kindness.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When to Use What
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Waiting on network, timers, IndexedDB&lt;/td&gt;
&lt;td&gt;Promises / &lt;code&gt;async&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Short work between awaits&lt;/td&gt;
&lt;td&gt;Stay on the main thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large CPU work, UI must stay live&lt;/td&gt;
&lt;td&gt;Web Worker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worker grows into many methods&lt;/td&gt;
&lt;td&gt;Comlink&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Many concurrent jobs&lt;/td&gt;
&lt;td&gt;workerpool (browser) or Piscina (Node)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Huge shared frames/tensors&lt;/td&gt;
&lt;td&gt;SharedArrayBuffer after measuring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I/O-bound or tiny work&lt;/td&gt;
&lt;td&gt;Do not add a worker&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Not every freeze needs a worker. Tiny work and pure I/O usually do not. Reach for parallelism when the UI must stay alive &lt;em&gt;and&lt;/em&gt; the CPU has real work to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;async&lt;/code&gt; does not mean "runs in parallel." It means "can wait without busy-waiting on this thread."&lt;/p&gt;

&lt;p&gt;A Web Worker is the tool that runs heavy JavaScript somewhere else while the UI thread stays free. Wrap the reply in a Promise so your app code stays readable — the &lt;code&gt;await&lt;/code&gt; is for the message, not for the math.&lt;/p&gt;

&lt;p&gt;Then climb only as far as you need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Raw &lt;code&gt;postMessage&lt;/code&gt; (&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/02-raw-web-worker" rel="noopener noreferrer"&gt;example 02&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Comlink (&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/03-comlink-worker" rel="noopener noreferrer"&gt;example 03&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A pool (&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/05-workerpool" rel="noopener noreferrer"&gt;examples 05&lt;/a&gt; / &lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/06-piscina-node" rel="noopener noreferrer"&gt;06&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;SharedArrayBuffer (&lt;a href="https://github.com/mrajaeim/Advanced-JS-Execution/tree/main/examples/04-shared-array-buffer" rel="noopener noreferrer"&gt;example 04&lt;/a&gt;) when memory movement is the bottleneck&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The fastest way to feel the difference: clone the repo, run &lt;code&gt;01&lt;/code&gt; next to &lt;code&gt;02&lt;/code&gt;, dismiss each alert, and click &lt;strong&gt;Ping UI&lt;/strong&gt; in both. In &lt;code&gt;01&lt;/code&gt; the button label freezes; in &lt;code&gt;02&lt;/code&gt; it keeps counting. That comparison teaches the architecture faster than any diagram.&lt;/p&gt;

&lt;p&gt;What was the first job you tried to "fix" with &lt;code&gt;async/await&lt;/code&gt; that still froze the tab?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Your JavaScript Runs in the Wrong Order</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Sun, 19 Jul 2026 16:30:00 +0000</pubDate>
      <link>https://dev.to/mrajaeim/why-your-javascript-runs-in-the-wrong-order-2fki</link>
      <guid>https://dev.to/mrajaeim/why-your-javascript-runs-in-the-wrong-order-2fki</guid>
      <description>&lt;p&gt;Copy this into your browser console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably expect: &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You get: &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nothing is broken. JavaScript is doing exactly what it was designed to do. The confusing part is that the language &lt;em&gt;looks&lt;/em&gt; like it runs top to bottom, but it does not always work that way.&lt;/p&gt;

&lt;p&gt;In this article you will learn three ideas that explain almost every async surprise in JavaScript:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;call stack&lt;/strong&gt; (what runs right now)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;event loop&lt;/strong&gt; (what runs next)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async code&lt;/strong&gt; (how waiting fits in without freezing your app)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No prior knowledge of the event loop required. We will build the mental model step by step.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What developers expect
&lt;/h3&gt;

&lt;p&gt;Most of us learn JavaScript like this: the engine reads your file line by line and runs each line in order.&lt;/p&gt;

&lt;p&gt;That mental model works fine for code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bye&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output: &lt;code&gt;hello&lt;/code&gt;, then &lt;code&gt;bye&lt;/code&gt;. Easy.&lt;/p&gt;

&lt;p&gt;Then we add &lt;code&gt;setTimeout&lt;/code&gt;, Promises, and &lt;code&gt;async/await&lt;/code&gt;. The same mental model breaks.&lt;/p&gt;

&lt;h3&gt;
  
  
  A common frustrating moment
&lt;/h3&gt;

&lt;p&gt;You are debugging a feature. You sprinkle &lt;code&gt;console.log&lt;/code&gt; calls to trace the flow. The logs come back in an order that makes no sense.&lt;/p&gt;

&lt;p&gt;Or you build a search box. Each keystroke fires a fetch. Sometimes an older response overwrites a newer one. The bug feels random.&lt;/p&gt;

&lt;p&gt;Or you use &lt;code&gt;async/await&lt;/code&gt; thinking the UI will stay responsive, but a heavy loop after an &lt;code&gt;await&lt;/code&gt; still freezes the page.&lt;/p&gt;

&lt;p&gt;These are not separate mysteries. They all come from the same root cause: &lt;strong&gt;JavaScript can only run one piece of code at a time, but it still needs to handle waiting.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why It Happens
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Part 1: The call stack
&lt;/h3&gt;

&lt;p&gt;Think of the call stack as JavaScript's to-do list for &lt;em&gt;right now&lt;/em&gt;. It is a Last-In, First-Out (LIFO) structure: the newest call sits on top and is the only thing that runs.&lt;/p&gt;

&lt;p&gt;When your code calls a function, that function goes on top of the stack. When the function finishes, it comes off. The engine always works on whatever is on top.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;b&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;b&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While &lt;code&gt;c&lt;/code&gt; runs, the stack looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────┐
│   c()   │  ← running now
├─────────┤
│   b()   │
├─────────┤
│   a()   │
└─────────┘
  CALL STACK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rules of the call stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only one function runs at a time&lt;/li&gt;
&lt;li&gt;Synchronous code runs immediately, in call order&lt;/li&gt;
&lt;li&gt;When the stack is empty, the current "turn" of synchronous work is done&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last rule is the key to everything that follows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2: JavaScript cannot wait on the stack
&lt;/h3&gt;

&lt;p&gt;Say you write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// network request&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If JavaScript actually &lt;em&gt;stopped and waited&lt;/em&gt; for the network, your entire page would freeze. No clicks. No scrolling. No animations.&lt;/p&gt;

&lt;p&gt;So the engine does something smarter. It &lt;strong&gt;starts&lt;/strong&gt; the fetch, then &lt;strong&gt;moves on&lt;/strong&gt; to the next line. When the network responds later, a callback runs.&lt;/p&gt;

&lt;p&gt;That "run later" part is handled outside the call stack, by the &lt;strong&gt;event loop&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 3: The event loop in plain English
&lt;/h3&gt;

&lt;p&gt;Part 1 showed what runs &lt;strong&gt;right now&lt;/strong&gt; (the call stack).&lt;/p&gt;

&lt;p&gt;Part 2 showed that &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;setTimeout&lt;/code&gt; cannot block the stack while they wait.&lt;/p&gt;

&lt;p&gt;So where does that waiting work go? And when does the "run later" code actually execute?&lt;/p&gt;

&lt;p&gt;That is what the &lt;strong&gt;event loop&lt;/strong&gt; handles. It is the coordinator that lets single-threaded JavaScript stay non-blocking: slow work (network, timers, I/O) is handed to the browser or Node.js, and the loop decides when their callbacks get a turn on the call stack.&lt;/p&gt;

&lt;h4&gt;
  
  
  The pieces that work together
&lt;/h4&gt;

&lt;p&gt;Four structures share the job. Think of them as one runtime, not four separate engines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------------------------------------------------+
|                     Browser / Node.js                       |
|                                                             |
|   +-------------------+             +-------------------+   |
|   |    Call Stack     |             |  Web / Node APIs  |   |
|   |  (synchronous)    |             | (timers, fetch…)  |   |
|   +---------+---------+             +---------+---------+   |
|             ^                                 |             |
|             |  pushes work                    | finishes    |
|             |  onto the stack                 v             |
|     +-------+-------+               +---------+---------+   |
|     |  Event Loop   |               |  Microtask Queue  |   |
|     | (coordinator) |&amp;lt;--------------+ (Promises, await) |   |
|     +---------------+   drains      +---------+---------+   |
|                             before            ^             |
|                             the next          |             |
|                                     +---------+---------+   |
|                                     |  Macrotask Queue  |   |
|                                     | (setTimeout, DOM) |   |
|                                     +-------------------+   |
+-------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Role in one sentence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Call stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;LIFO stack of the function that is running &lt;em&gt;right now&lt;/em&gt;. Frames go on when called, off when finished.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web / Node APIs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Work the runtime owns outside your JS thread: timers, &lt;code&gt;fetch&lt;/code&gt;, DOM events, and similar I/O.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microtask queue&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High-priority FIFO line for Promise callbacks (&lt;code&gt;.then&lt;/code&gt; / &lt;code&gt;.catch&lt;/code&gt; / &lt;code&gt;.finally&lt;/code&gt;), &lt;code&gt;await&lt;/code&gt; continuations, and &lt;code&gt;queueMicrotask()&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Macrotask queue&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lower-priority FIFO line for timer callbacks, many I/O callbacks, and UI events. Often called the task / callback queue.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The event loop itself is not a background thread. It is the rulebook that moves work between these pieces.&lt;/p&gt;

&lt;h4&gt;
  
  
  A simple analogy
&lt;/h4&gt;

&lt;p&gt;Imagine a cashier (the call stack) who can only help one customer at a time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Synchronous code&lt;/strong&gt; walks up and gets served immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;fetch&lt;/code&gt;&lt;/strong&gt; are like customers who step aside and wait for a text message ("your order is ready") — that waiting happens in the Web / Node APIs.&lt;/li&gt;
&lt;li&gt;When the cashier has no one in line, they check two waiting lists before calling the next walk-in customer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those two waiting lists are the important part. JavaScript does not use one generic "later" queue. It uses &lt;strong&gt;two&lt;/strong&gt;, with a strict priority order.&lt;/p&gt;

&lt;h4&gt;
  
  
  The two waiting lists
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Waiting list&lt;/th&gt;
&lt;th&gt;Plain name&lt;/th&gt;
&lt;th&gt;What goes here&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Microtask queue&lt;/td&gt;
&lt;td&gt;the Promise line&lt;/td&gt;
&lt;td&gt;callbacks that should run soon&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.then()&lt;/code&gt;, &lt;code&gt;await&lt;/code&gt; continuations, &lt;code&gt;queueMicrotask()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Macrotask queue&lt;/td&gt;
&lt;td&gt;the timer/event line&lt;/td&gt;
&lt;td&gt;callbacks that can wait a bit longer&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;setTimeout&lt;/code&gt;, clicks, network I/O callbacks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Think of it like airport boarding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microtasks&lt;/strong&gt; = priority boarding (Promises go first)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Macrotasks&lt;/strong&gt; = general boarding (&lt;code&gt;setTimeout&lt;/code&gt;, UI events)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What the event loop does, step by step
&lt;/h4&gt;

&lt;p&gt;The engine follows one continuous checklist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Run synchronous code until the call stack is empty
2. Hand async APIs (setTimeout, fetch, …) to Web / Node APIs and keep going
3. When background work finishes, drop its callback into the microtask
   or macrotask queue (depending on the API)
4. With an empty stack, drain EVERY microtask — including ones spawned
   by other microtasks
5. Take exactly ONE macrotask, push it onto the call stack, and run it
6. Go back to step 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One sentence version: &lt;strong&gt;sync first, then all Promises, then one timer/event, then repeat.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That "every microtask" step matters. If a Promise callback schedules another Promise callback, the new one still runs before any macrotask. A busy microtask chain can delay timers and UI events.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk35ljx55fb658rw3qy1h.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk35ljx55fb658rw3qy1h.png" alt="call stack, event loop, and async code in JavaScript" width="732" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Where &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;fetch&lt;/code&gt; fit
&lt;/h4&gt;

&lt;p&gt;When you call &lt;code&gt;setTimeout&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt;, the engine does not run your callback immediately. It hands the waiting job to the browser (or Node.js). That happens outside the call stack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your JS code                    Browser / Node (outside the stack)
─────────────                   ──────────────────────────────────
setTimeout(fn, 0)    ────────►   timer starts...
fetch('/api')        ────────►   network request starts...
                                 (your code keeps running)
                                 ...time passes...
timer fires          ◄────────   puts fn in the timer/event line
response arrives     ◄────────   puts .then callback in the Promise line
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpd3q4rfjzww0jenvmkkh.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpd3q4rfjzww0jenvmkkh.png" alt="Browser / Node (outside the stack)" width="800" height="770"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your callback only runs when the event loop picks it from a waiting list and puts it back on the call stack.&lt;/p&gt;

&lt;h4&gt;
  
  
  Walk through our opening example
&lt;/h4&gt;

&lt;p&gt;Here is the snippet again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1: synchronous code (call stack)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Line&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Printed so far&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log('1')&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;runs immediately&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setTimeout(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;browser starts a timer; when it fires, the callback waits in the &lt;strong&gt;timer/event line&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.then(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;callback waits in the &lt;strong&gt;Promise line&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log('4')&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;runs immediately&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Call stack is now empty. Synchronous work is done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Promise line (microtasks)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The engine drains the microtask queue completely before touching timers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What runs&lt;/th&gt;
&lt;th&gt;Printed so far&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log('3')&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 3: timer/event line (one macrotask)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now the loop takes exactly one macrotask — the &lt;code&gt;setTimeout&lt;/code&gt; callback:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What runs&lt;/th&gt;
&lt;th&gt;Printed so far&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log('2')&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Final answer:&lt;/strong&gt; &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Why that order sticks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt; and &lt;code&gt;4&lt;/code&gt; are pure sync work on the call stack, so they print first.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setTimeout(..., 0)&lt;/code&gt; registers a timer right away; when it expires, the callback lands in the &lt;strong&gt;macrotask&lt;/strong&gt; queue — not on the stack.&lt;/li&gt;
&lt;li&gt;The resolved Promise schedules its callback in the &lt;strong&gt;microtask&lt;/strong&gt; queue.&lt;/li&gt;
&lt;li&gt;After the main script finishes, the event loop clears microtasks before any macrotask, so &lt;code&gt;3&lt;/code&gt; prints before &lt;code&gt;2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;3&lt;/code&gt; beats &lt;code&gt;2&lt;/code&gt; because Promise callbacks always run before &lt;code&gt;setTimeout&lt;/code&gt; callbacks, even when the timer is set to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The one rule to remember
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Sync code first. Then all Promises. Then one timer or event. Then repeat.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fst3izq7adbcost8fb122.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fst3izq7adbcost8fb122.png" alt="The one rule to remember Sync code first Then all Promises Then one timer or event Then repeat" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you remember that, the opening example stops feeling random.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 4: What &lt;code&gt;async/await&lt;/code&gt; actually does
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;async/await&lt;/code&gt; is just Promise syntax. It does not pause the entire program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt; prints (sync)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;load()&lt;/code&gt; starts, &lt;code&gt;A&lt;/code&gt; prints (sync)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;await&lt;/code&gt; hits the network and &lt;strong&gt;steps out&lt;/strong&gt; of the function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;2&lt;/code&gt; prints (sync) because the stack is free&lt;/li&gt;
&lt;li&gt;Fetch finishes, &lt;code&gt;B&lt;/code&gt; prints (microtask)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Output: &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The code &lt;em&gt;after&lt;/em&gt; &lt;code&gt;await&lt;/code&gt; does not run when the network finishes inside your function like a blocking pause. It gets scheduled as a microtask for later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Manual Solution: Trace the Code by Hand
&lt;/h2&gt;

&lt;p&gt;You do not need tools to predict small examples. Label each line, then follow the event loop rules.&lt;/p&gt;

&lt;p&gt;Take our opening snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                                    &lt;span class="c1"&gt;// SYNC&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;               &lt;span class="c1"&gt;// schedules MACROTASK&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;    &lt;span class="c1"&gt;// schedules MICROTASK&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                                    &lt;span class="c1"&gt;// SYNC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now walk through it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Round 1: synchronous code&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Call stack&lt;/th&gt;
&lt;th&gt;Console output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log('1')&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[log]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setTimeout(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[setTimeout]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(schedules &lt;code&gt;2&lt;/code&gt; for later)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.then(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[then]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(schedules &lt;code&gt;3&lt;/code&gt; for later)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log('4')&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[log]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stack empty&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Round 2: microtasks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Promise callback runs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Console output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Round 3: one macrotask&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;setTimeout&lt;/code&gt; callback runs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Console output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Final output:&lt;/strong&gt; &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That is the full manual process. For any small snippet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run every synchronous line until the stack is empty&lt;/li&gt;
&lt;li&gt;Run every microtask&lt;/li&gt;
&lt;li&gt;Run one macrotask&lt;/li&gt;
&lt;li&gt;Repeat from step 2&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Verify in DevTools
&lt;/h3&gt;

&lt;p&gt;Open Chrome DevTools, go to &lt;strong&gt;Sources&lt;/strong&gt;, and set a breakpoint inside a &lt;code&gt;.then()&lt;/code&gt; callback. When execution pauses, look at the &lt;strong&gt;Call Stack&lt;/strong&gt; panel on the right. It shows exactly which functions are active.&lt;/p&gt;

&lt;p&gt;For log-order bugs, numbered labels help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[sync] user clicked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use this in code reviews all the time. It is simple and it works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Drawbacks of the Manual Process
&lt;/h2&gt;

&lt;p&gt;Tracing by hand is great for interview questions and 5-line snippets. It gets painful in real apps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React, Vue, and other frameworks schedule work you cannot see&lt;/li&gt;
&lt;li&gt;Network responses arrive in unpredictable order&lt;/li&gt;
&lt;li&gt;One file may mix &lt;code&gt;setTimeout&lt;/code&gt;, Promises, and &lt;code&gt;await&lt;/code&gt; in ways that are hard to track&lt;/li&gt;
&lt;li&gt;It is easy to forget the rule: &lt;strong&gt;all microtasks run before the next macrotask&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Knowing the rules is not the same as writing code that survives fast user input and slow networks. That is where patterns help.&lt;/p&gt;




&lt;h2&gt;
  
  
  Better Solution: Three Rules for Async Code
&lt;/h2&gt;

&lt;p&gt;Instead of tracing every line in your head, write code that matches how the runtime works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 1: Keep synchronous blocks short.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Long loops on the main thread block everything, even after an &lt;code&gt;await&lt;/code&gt;. If work is heavy, break it into chunks or move it to a Web Worker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 2: Use &lt;code&gt;async/await&lt;/code&gt; to sequence steps in one flow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When step B needs the result of step A, &lt;code&gt;await&lt;/code&gt; is the right tool. It keeps the logic readable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 3: Guard against out-of-order async results.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the user can trigger the same async action multiple times (search, pagination, tab switches), ignore or cancel stale results.&lt;/p&gt;

&lt;p&gt;These three rules fix most production async bugs I have seen.&lt;/p&gt;




&lt;h2&gt;
  
  
  Complete Code
&lt;/h2&gt;

&lt;p&gt;Here is a before/after for a search box. This is the full example we will break down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (buggy):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;searchInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/search?q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;renderResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// may render stale data&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (fixed):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;activeController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;searchInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Cancel the previous in-flight request&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeController&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;activeController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;activeController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`/api/search?q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;activeController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;renderResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// a newer search started, ignore this one&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Breakdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why the "before" code breaks
&lt;/h3&gt;

&lt;p&gt;Each keystroke starts a fetch. All requests run at the same time. Whichever response arrives &lt;strong&gt;last&lt;/strong&gt; wins, not whichever query is &lt;strong&gt;current&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the user types &lt;code&gt;react&lt;/code&gt; quickly, the response for &lt;code&gt;re&lt;/code&gt; might arrive after &lt;code&gt;react&lt;/code&gt;. The UI shows results for &lt;code&gt;re&lt;/code&gt;. That looks like async code is "random." It is not. The event loop is working fine. The code just never checks whether the result is still relevant.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;activeController&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A variable that holds the current &lt;code&gt;AbortController&lt;/code&gt;. Think of it as a remote control for the in-flight fetch.&lt;/p&gt;

&lt;p&gt;When the user types a new character, we abort the old request before starting a new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;AbortController&lt;/code&gt; and &lt;code&gt;signal&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;fetch&lt;/code&gt; accepts a &lt;code&gt;signal&lt;/code&gt; option. When you call &lt;code&gt;controller.abort()&lt;/code&gt;, the in-flight fetch rejects with an &lt;code&gt;AbortError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is better than ignoring stale results silently. It actually cancels work you no longer need.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;try/catch&lt;/code&gt; block
&lt;/h3&gt;

&lt;p&gt;Not every aborted request is an error worth showing. &lt;code&gt;AbortError&lt;/code&gt; means "a newer search replaced this one." We return early and do nothing.&lt;/p&gt;

&lt;p&gt;Real errors (network down, 500 response) still go to &lt;code&gt;showError&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Example: Step by Step
&lt;/h2&gt;

&lt;p&gt;Let us trace the fixed search box when a user types &lt;code&gt;r&lt;/code&gt;, then &lt;code&gt;re&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keystroke 1: user types &lt;code&gt;r&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYNC:  input handler runs
SYNC:  abort() called (nothing to abort yet)
SYNC:  fetch('/api/search?q=r') starts (network waits in background)
SYNC:  handler returns, stack is empty
...later...
MICRO: await continuation runs, renderResults for "r"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keystroke 2: user types &lt;code&gt;re&lt;/code&gt; (before &lt;code&gt;r&lt;/code&gt; responds)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYNC:  input handler runs
SYNC:  abort() cancels the "r" request
SYNC:  fetch('/api/search?q=re') starts
SYNC:  handler returns
MICRO: "r" fetch rejects with AbortError → catch block returns early
...later...
MICRO: "re" fetch resolves → renderResults for "re"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UI always shows results for the latest query. No race condition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Back to the classic log-order example
&lt;/h3&gt;

&lt;p&gt;Paste this in your console and watch it run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;What runs&lt;/th&gt;
&lt;th&gt;Output so far&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sync&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microtasks&lt;/td&gt;
&lt;td&gt;Promise callback&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Macrotask&lt;/td&gt;
&lt;td&gt;setTimeout callback&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once you have done this two or three times, the order stops feeling random.&lt;/p&gt;




&lt;h2&gt;
  
  
  Warnings and Edge Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Blocking the call stack freezes everything
&lt;/h3&gt;

&lt;p&gt;JavaScript has one main thread for your page script. A long sync job — resizing a huge image in a loop, parsing a massive JSON blob, or an accidental infinite loop — never leaves the call stack. While that frame is stuck, the event loop cannot drain microtasks or macrotasks. Clicks queue up. Animations stall. The tab looks dead even though "async" APIs are still waiting in the background.&lt;/p&gt;

&lt;p&gt;That is why heavy CPU work belongs in chunks or in a Web Worker, not in a tight loop after an &lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Timers are minimums, not appointments
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;setTimeout(fn, 1000)&lt;/code&gt; does not promise that &lt;code&gt;fn&lt;/code&gt; runs at the one-second mark. It means: after at least 1000ms, the callback &lt;em&gt;may&lt;/em&gt; enter the macrotask queue. If the stack is busy, or microtasks keep spawning, the callback waits longer. Treat the delay as a floor, not a schedule.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; does not mean "run immediately after sync code"
&lt;/h3&gt;

&lt;p&gt;It means "schedule a macrotask." Promise callbacks still run first. If you need to defer work to after the current synchronous block but before timers, use &lt;code&gt;queueMicrotask()&lt;/code&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;await&lt;/code&gt; does not run fetches in parallel
&lt;/h3&gt;

&lt;p&gt;This is sequential (B waits for A):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs both at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Long sync work after &lt;code&gt;await&lt;/code&gt; still blocks the UI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;heavy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_000_000_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// blocks clicks and scrolling&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;await&lt;/code&gt; only yields &lt;em&gt;before&lt;/em&gt; the loop, not during it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node.js has one extra queue
&lt;/h3&gt;

&lt;p&gt;In Node, &lt;code&gt;process.nextTick()&lt;/code&gt; runs even before microtasks. Browser code rarely needs this, but Node tutorials lean on it. Node's loop is also organized into phases (timers, I/O, check, close, and so on). The browser-friendly story in this article still holds for most app code; when you debug server timers and &lt;code&gt;nextTick&lt;/code&gt; ordering, read the &lt;a href="https://nodejs.org/learn/asynchronous-work/event-loop-timers-and-nexttick" rel="noopener noreferrer"&gt;Node event loop guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frameworks add their own scheduling
&lt;/h3&gt;

&lt;p&gt;React 18 batches state updates differently than React 17. If your logs inside &lt;code&gt;useEffect&lt;/code&gt; do not match a bare-bones example, the framework may be batching work. Always test in your real setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use This Knowledge
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Reach for this mental model when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Console logs appear in a confusing order&lt;/li&gt;
&lt;li&gt;A fetch-heavy UI shows stale data&lt;/li&gt;
&lt;li&gt;You are choosing between &lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;Promise&lt;/code&gt;, and &lt;code&gt;queueMicrotask&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You are reviewing async code in a pull request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This alone is not enough when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have CPU-heavy work (use a Web Worker)&lt;/li&gt;
&lt;li&gt;You need true multi-core parallelism&lt;/li&gt;
&lt;li&gt;You are doing server-side concurrency in Node (look into worker threads)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On a team&lt;/strong&gt;, it helps to agree on one pattern for canceling stale fetches (&lt;code&gt;AbortController&lt;/code&gt; is a good default) and to ask in review: "what happens if the user triggers this twice before the first call finishes?"&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;JavaScript runs synchronous code on the &lt;strong&gt;call stack&lt;/strong&gt; first. When the stack is empty, the &lt;strong&gt;event loop&lt;/strong&gt; drains every microtask (Promises, &lt;code&gt;await&lt;/code&gt;), then runs one macrotask (&lt;code&gt;setTimeout&lt;/code&gt;, events), and repeats.&lt;/p&gt;

&lt;p&gt;That single rule explains why &lt;code&gt;1, 4, 3, 2&lt;/code&gt; is the correct output for our opening example. It also explains why search boxes need cancellation logic, and why &lt;code&gt;async/await&lt;/code&gt; alone does not keep the UI smooth during heavy loops.&lt;/p&gt;

&lt;p&gt;You do not need to memorize every edge case. Remember the big picture: &lt;strong&gt;sync first, then microtasks, then one macrotask.&lt;/strong&gt; Everything else is a variation on that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go further
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model" rel="noopener noreferrer"&gt;MDN: JavaScript execution model&lt;/a&gt; — the formal picture of the stack, tasks, and microtasks&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/learn/asynchronous-work/event-loop-timers-and-nexttick" rel="noopener noreferrer"&gt;Node.js: The Node.js Event Loop&lt;/a&gt; — how phases and &lt;code&gt;nextTick&lt;/code&gt; differ from the browser story&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a follow-up deep dive, the natural next stops are: how &lt;code&gt;async/await&lt;/code&gt; maps onto that visual timeline, how to hunt a specific out-of-order race, or how Node's phases differ when you leave the browser.&lt;/p&gt;

&lt;p&gt;What was the first async bug that made you stop and question how JavaScript actually works?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>vue</category>
    </item>
    <item>
      <title>Stop Rebasing Every Time: A Safer Way to Keep Your Git Branch Updated with `master`</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Sat, 18 Jul 2026 18:30:00 +0000</pubDate>
      <link>https://dev.to/mrajaeim/stop-rebasing-every-time-a-safer-way-to-keep-your-git-branch-updated-with-master-4ojh</link>
      <guid>https://dev.to/mrajaeim/stop-rebasing-every-time-a-safer-way-to-keep-your-git-branch-updated-with-master-4ojh</guid>
      <description>&lt;p&gt;If you work on long-lived feature branches, you've probably experienced this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;master&lt;/code&gt; (or &lt;code&gt;main&lt;/code&gt;) keeps moving.&lt;/li&gt;
&lt;li&gt;Your branch falls behind.&lt;/li&gt;
&lt;li&gt;Pull requests become harder to review.&lt;/li&gt;
&lt;li&gt;Merge conflicts get bigger every day.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many teams solve this by &lt;strong&gt;rebasing&lt;/strong&gt; their feature branches.&lt;/p&gt;

&lt;p&gt;Others—including many enterprise teams—prefer &lt;strong&gt;merging&lt;/strong&gt; the latest &lt;code&gt;master&lt;/code&gt; into the feature branch to preserve commit history and avoid rewriting commits that may already be shared.&lt;/p&gt;

&lt;p&gt;If your workflow uses merge instead of rebase, this article shows how to make the process much faster with a custom Git alias.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Imagine your repository looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;master
A──B──C──D

feature/login
     \
      E──F
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While you're developing, your teammates merge several pull requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;master
A──B──C──D──G──H──I

feature/login
     \
      E──F
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your feature branch is missing the latest changes.&lt;/p&gt;

&lt;p&gt;If you don't sync it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;merge conflicts accumulate&lt;/li&gt;
&lt;li&gt;CI may fail unexpectedly&lt;/li&gt;
&lt;li&gt;testing becomes less reliable&lt;/li&gt;
&lt;li&gt;your eventual pull request becomes much harder to review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping your branch up-to-date regularly makes integration much smoother.&lt;/p&gt;




&lt;h2&gt;
  
  
  Updating Your Branch Manually
&lt;/h2&gt;

&lt;p&gt;Suppose you're working on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feature/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and want to sync it with &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, fetch the latest changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switch to your feature branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout feature/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reset your local branch to match the remote version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; origin/feature/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why reset?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This ensures your local branch exactly matches the remote branch before merging. It's useful if your local branch is only a working copy of the remote branch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Any unpushed commits will be permanently deleted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Merge the latest &lt;code&gt;master&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git merge &lt;span class="nt"&gt;--no-ff&lt;/span&gt; origin/master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, push the updated branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your history now becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;master
A──B──C──D──G──H──I
               \
feature/login   M
      \        /
       E──────F
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;strong&gt;M&lt;/strong&gt; is the merge commit.&lt;/p&gt;




&lt;h2&gt;
  
  
  That's a Lot of Typing...
&lt;/h2&gt;

&lt;p&gt;Every time you want to synchronize a branch, you're repeating the same commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch
git checkout feature/login
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; origin/feature/login
git merge &lt;span class="nt"&gt;--no-ff&lt;/span&gt; origin/master
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this dozens of times each week, it becomes repetitive.&lt;/p&gt;

&lt;p&gt;Fortunately, Git aliases can automate the workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating a Git Alias
&lt;/h2&gt;

&lt;p&gt;Run the following command once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.sync-branch &lt;span class="s1"&gt;'!f() {
    git fetch &amp;amp;&amp;amp;
    git checkout "$1" &amp;amp;&amp;amp;
    git diff --quiet &amp;amp;&amp;amp;
    git diff --cached --quiet &amp;amp;&amp;amp;
    git reset --hard origin/$1 &amp;amp;&amp;amp;
    git merge --no-ff origin/${2:-master};
}; f'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a new command called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git sync-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How to Use It
&lt;/h2&gt;

&lt;p&gt;Sync your branch with &lt;code&gt;master&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git sync-branch feature/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or sync it with another branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git sync-branch feature/login develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which is equivalent to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch
git checkout feature/login
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; origin/feature/login
git merge &lt;span class="nt"&gt;--no-ff&lt;/span&gt; origin/develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Does the Alias Do?
&lt;/h2&gt;

&lt;p&gt;Let's break it down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Downloads the latest commits from the remote.&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switches to the target branch.&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--quiet&lt;/span&gt;
git diff &lt;span class="nt"&gt;--cached&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensures there are &lt;strong&gt;no uncommitted changes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If your working tree isn't clean, the alias stops instead of accidentally deleting work.&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; origin/&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Makes your local branch identical to the remote branch.&lt;/p&gt;

&lt;p&gt;This removes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local commits&lt;/li&gt;
&lt;li&gt;staged changes&lt;/li&gt;
&lt;li&gt;unstaged changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;that haven't been pushed.&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git merge &lt;span class="nt"&gt;--no-ff&lt;/span&gt; origin/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;master&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Merges the latest &lt;code&gt;master&lt;/code&gt; (or another specified branch) into your feature branch while always creating a merge commit.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should You Use This?
&lt;/h2&gt;

&lt;p&gt;This workflow is ideal if your team:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prefers merge over rebase&lt;/li&gt;
&lt;li&gt;wants to preserve merge history&lt;/li&gt;
&lt;li&gt;frequently syncs long-running feature branches&lt;/li&gt;
&lt;li&gt;already pushes work to the remote regularly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is &lt;strong&gt;not&lt;/strong&gt; recommended if you often keep local-only commits that haven't been pushed yet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important Warnings
&lt;/h2&gt;

&lt;p&gt;⚠️ This alias uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have local commits or changes that are &lt;strong&gt;not pushed&lt;/strong&gt;, they will be permanently deleted.&lt;/p&gt;

&lt;p&gt;Before using it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;commit your work&lt;/li&gt;
&lt;li&gt;push your commits&lt;/li&gt;
&lt;li&gt;or stash your changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Always understand what a Git alias does before adding it to your global configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;One of Git's most underused features is aliases.&lt;/p&gt;

&lt;p&gt;Small automations like this can eliminate repetitive commands and reduce mistakes, especially when you perform the same workflow dozens of times a week.&lt;/p&gt;

&lt;p&gt;If your team follows a merge-based workflow, a &lt;code&gt;sync-branch&lt;/code&gt; alias can save time while keeping every feature branch aligned with the latest changes from &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>gitlab</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Hidden Windows Port Issue: Why Your New App Won't Start (Especially After Using a VPN) and How to Fix It</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Fri, 17 Jul 2026 08:42:16 +0000</pubDate>
      <link>https://dev.to/mrajaeim/the-hidden-windows-port-issue-why-your-new-app-wont-start-especially-after-using-a-vpn-and-how-12jj</link>
      <guid>https://dev.to/mrajaeim/the-hidden-windows-port-issue-why-your-new-app-wont-start-especially-after-using-a-vpn-and-how-12jj</guid>
      <description>&lt;p&gt;Have you ever cloned a new project, ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;only to be greeted with an error like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: listen EADDRINUSE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind: An attempt was made to access a socket in a way forbidden by its access permissions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The strange part?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nothing appears to be using the port.&lt;/li&gt;
&lt;li&gt;Restarting the application doesn't help.&lt;/li&gt;
&lt;li&gt;Even changing to another port sometimes fails.&lt;/li&gt;
&lt;li&gt;The issue often starts after connecting to a VPN, enabling Docker Desktop, WSL2, or Hyper-V.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I recently ran into exactly this problem, and the fix was surprisingly simple.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does This Happen?
&lt;/h2&gt;

&lt;p&gt;On Windows, the &lt;strong&gt;Host Network Service (HNS)&lt;/strong&gt; manages networking for technologies such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Desktop&lt;/li&gt;
&lt;li&gt;WSL2&lt;/li&gt;
&lt;li&gt;Hyper-V&lt;/li&gt;
&lt;li&gt;Windows Containers&lt;/li&gt;
&lt;li&gt;Some VPN software&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes HNS reserves or holds ports even after applications have exited, preventing new processes from binding to them. This behavior has also been reported by developers using Docker, Hyper-V, and WSL networking.&lt;/p&gt;

&lt;p&gt;As a result, Windows behaves as if the port is already occupied.&lt;/p&gt;




&lt;h2&gt;
  
  
  Symptoms
&lt;/h2&gt;

&lt;p&gt;You may notice errors like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EADDRINUSE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Address already in use
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Only one usage of each socket address is normally permitted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or Docker errors related to port publishing.&lt;/p&gt;

&lt;p&gt;This is especially common after:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connecting or disconnecting from a VPN&lt;/li&gt;
&lt;li&gt;Starting Docker Desktop&lt;/li&gt;
&lt;li&gt;Using WSL2&lt;/li&gt;
&lt;li&gt;Working with Hyper-V virtual machines&lt;/li&gt;
&lt;li&gt;Switching between networking environments&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;PowerShell as Administrator&lt;/strong&gt; and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hns&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Windows asks whether dependent services should also be stopped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The following services are dependent on the Host Network Service...
Do you want to continue? (Y/N)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;In many cases, your application will immediately be able to bind to the port again.&lt;/p&gt;




&lt;h2&gt;
  
  
  If That Doesn't Work
&lt;/h2&gt;

&lt;p&gt;If the issue persists, check whether Windows has reserved your port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;netsh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ipv4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;excludedportrange&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your desired port falls inside one of the excluded ranges, Windows has reserved it for networking components such as Hyper-V or HNS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Restarting HNS Works
&lt;/h2&gt;

&lt;p&gt;Stopping the Host Network Service forces Windows to rebuild its networking state and releases stale network resources.&lt;/p&gt;

&lt;p&gt;It's much faster than:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restarting your computer&lt;/li&gt;
&lt;li&gt;Reinstalling Docker&lt;/li&gt;
&lt;li&gt;Reinstalling your VPN&lt;/li&gt;
&lt;li&gt;Spending an hour wondering why &lt;code&gt;localhost:3000&lt;/code&gt; suddenly stopped working&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When Should You Use This?
&lt;/h2&gt;

&lt;p&gt;This solution is worth trying if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your development server suddenly won't start.&lt;/li&gt;
&lt;li&gt;Docker reports port binding failures.&lt;/li&gt;
&lt;li&gt;A port appears to be in use but nothing is listening on it.&lt;/li&gt;
&lt;li&gt;The issue began after using Docker Desktop, WSL2, Hyper-V, or a VPN.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The next time Windows insists that a port is already in use—even though every process says otherwise—don't immediately assume your application is broken.&lt;/p&gt;

&lt;p&gt;Try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hns&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has saved me more than once, and hopefully it saves you some debugging time too.&lt;/p&gt;

&lt;p&gt;If you've encountered other strange Windows networking issues, I'd love to hear how you solved them in the comments.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>networking</category>
      <category>webdev</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Data Processing Pipelines in Python Using Generators: Build Memory-Efficient ETL and AI Workflows</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Mon, 06 Jul 2026 13:42:47 +0000</pubDate>
      <link>https://dev.to/mrajaeim/data-processing-pipelines-in-python-using-generators-build-memory-efficient-etl-and-ai-workflows-2j27</link>
      <guid>https://dev.to/mrajaeim/data-processing-pipelines-in-python-using-generators-build-memory-efficient-etl-and-ai-workflows-2j27</guid>
      <description>&lt;p&gt;When processing large datasets, it's common to chain together multiple operations such as reading data, filtering records, transforming values, and writing the results somewhere else.&lt;/p&gt;

&lt;p&gt;A straightforward implementation often creates intermediate lists after each step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;filter_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;transformed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;transform_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transformed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this works well for small datasets, it becomes inefficient when processing millions of records because every intermediate result is stored in memory.&lt;/p&gt;

&lt;p&gt;A better approach is to use &lt;strong&gt;generator-based pipelines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Generators allow data to flow through each processing stage one item at a time, making your code more memory-efficient, composable, and easier to maintain.&lt;/p&gt;

&lt;p&gt;In this article, we'll build several generator pipelines ranging from simple text processing to ETL and computer vision workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Generator Pipeline?
&lt;/h2&gt;

&lt;p&gt;A generator pipeline consists of multiple independent stages.&lt;/p&gt;

&lt;p&gt;Each stage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receives an iterable (usually another generator).&lt;/li&gt;
&lt;li&gt;Processes each item.&lt;/li&gt;
&lt;li&gt;Produces items using &lt;code&gt;yield&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output of one stage becomes the input of the next.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fznzxp4joofp99okuc89e.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fznzxp4joofp99okuc89e.png" alt="Data Source -&gt; Read -&gt; Filter -&gt; Transform -&gt; Save / Output" width="799" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the biggest advantages is that only &lt;strong&gt;one item&lt;/strong&gt; typically moves through the pipeline at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example 1: Processing a Large Text File
&lt;/h2&gt;

&lt;p&gt;Suppose you have a multi-gigabyte log file and want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ignore comments&lt;/li&gt;
&lt;li&gt;Remove whitespace&lt;/li&gt;
&lt;li&gt;Convert everything to uppercase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each step becomes its own generator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remove_comments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;strip_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connecting them is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;strip_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;remove_comments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;read_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;log.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;strong&gt;nothing happens until the final loop starts consuming the generator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At any point, only a single line is being processed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example 2: Building a Simple ETL Pipeline
&lt;/h2&gt;

&lt;p&gt;Generator pipelines are a natural fit for ETL (Extract, Transform, Load).&lt;/p&gt;

&lt;p&gt;Let's define a simple model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Extract
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Charlie&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filter
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_adults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Transform
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Load
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Putting Everything Together
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;filter_adults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User(id=1, name='Alice', age=22)
User(id=3, name='Charlie', age=35)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage has a single responsibility, making the pipeline easy to extend and test.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example 3: Computer Vision Pipeline
&lt;/h2&gt;

&lt;p&gt;Generator pipelines are especially useful in machine learning and computer vision, where images can consume significant memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;load_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_paths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;predictions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of loading every image into memory first, images are loaded, processed, and predicted one at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example 4: Processing Database Records
&lt;/h2&gt;

&lt;p&gt;The same approach works for database queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_rows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchmany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cleaning the records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Saving them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;insert_into_new_db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only small batches are fetched from the database, while individual rows continue flowing through the pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using &lt;code&gt;yield from&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes a generator simply forwards another iterable.&lt;/p&gt;

&lt;p&gt;Instead of manually iterating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can delegate using &lt;code&gt;yield from&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;lst&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1, 2, 3, 4, 5]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;yield from&lt;/code&gt; makes generator composition cleaner and more readable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Generator Expressions
&lt;/h2&gt;

&lt;p&gt;For simple transformations, generator expressions are concise and expressive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0, 4, 16, 36, 64]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They work particularly well for lightweight pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building Configurable Pipelines
&lt;/h2&gt;

&lt;p&gt;As applications grow, it's useful to compose stages dynamically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections.abc&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now define a pipeline at runtime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1, 5, 17, 37, 65, 101, 145, 197, 257, 325]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it easy to swap, reorder, or add processing stages without modifying existing code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use Generator Pipelines?
&lt;/h2&gt;

&lt;p&gt;Generator pipelines provide several advantages over list-based processing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory efficient&lt;/strong&gt; — process one item at a time instead of storing intermediate collections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy evaluation&lt;/strong&gt; — work happens only when data is requested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable&lt;/strong&gt; — each stage performs a single responsibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable&lt;/strong&gt; — stages can be mixed and matched across pipelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt; — ideal for files, database cursors, streams, APIs, and machine learning datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testable&lt;/strong&gt; — each generator can be unit tested independently.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Where You'll See This Pattern
&lt;/h2&gt;

&lt;p&gt;Generator pipelines appear in many real-world systems, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ETL and data engineering workflows&lt;/li&gt;
&lt;li&gt;Log processing&lt;/li&gt;
&lt;li&gt;Web scraping&lt;/li&gt;
&lt;li&gt;CSV and JSON processing&lt;/li&gt;
&lt;li&gt;Computer vision preprocessing&lt;/li&gt;
&lt;li&gt;Machine learning data loaders&lt;/li&gt;
&lt;li&gt;Streaming applications&lt;/li&gt;
&lt;li&gt;API response processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you start recognizing the pattern, you'll find opportunities to use it in many Python projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Python generators are more than a way to iterate over data—they're a powerful tool for building clean, modular, and memory-efficient processing pipelines.&lt;/p&gt;

&lt;p&gt;By splitting your workflow into small generator stages, you can process datasets of virtually any size while keeping your code easy to understand, test, and extend.&lt;/p&gt;

&lt;p&gt;If you're working with large files, databases, APIs, or AI workloads, generator pipelines are a technique worth adding to your Python toolbox.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>programming</category>
      <category>performance</category>
    </item>
    <item>
      <title>🚖 Building a Scalable Frontend Mock Architecture with MSW, Factories, and Services (Uber-Like Example)</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Thu, 16 Oct 2025 21:30:01 +0000</pubDate>
      <link>https://dev.to/mrajaeim/building-a-scalable-frontend-mock-architecture-with-msw-factories-and-services-uber-like-3kgi</link>
      <guid>https://dev.to/mrajaeim/building-a-scalable-frontend-mock-architecture-with-msw-factories-and-services-uber-like-3kgi</guid>
      <description>&lt;p&gt;If you’ve ever built an app that depends on complex backend APIs — like a ride-sharing or delivery platform — you know the pain:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The backend isn’t ready yet… but I still need to test my UI, maps, and user flows.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Frontend developers often get stuck waiting for endpoints or using rigid JSON mocks that quickly become outdated.&lt;br&gt;
There’s a better way.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how to build a &lt;strong&gt;scalable mock architecture&lt;/strong&gt; for your frontend using &lt;strong&gt;Mock Service Worker (MSW)&lt;/strong&gt; — the modern way to simulate APIs directly in the browser or test environment.&lt;/p&gt;

&lt;p&gt;We’ll model a &lt;strong&gt;simplified Uber-like app&lt;/strong&gt; with entities like &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Drivers&lt;/code&gt;, &lt;code&gt;Vehicles&lt;/code&gt;, &lt;code&gt;Wallet&lt;/code&gt;, &lt;code&gt;MyLastTrips&lt;/code&gt;, and more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Note: The entities and examples here are simplified to illustrate the architecture.&lt;br&gt;
Real ride-sharing systems have more complex relationships and data flows.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  🧩 Why Traditional Mocks Don’t Scale
&lt;/h2&gt;

&lt;p&gt;Most frontend teams start with something simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mocks/handlers.ts&lt;/span&gt;
&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/drivers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.9&lt;/span&gt; &lt;span class="p"&gt;}]));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works… until it doesn’t.&lt;br&gt;
When your app grows — filters, pagination, dynamic routes, price estimates, and user-specific logic — this flat mock structure becomes unmaintainable.&lt;/p&gt;

&lt;p&gt;The solution?&lt;br&gt;
Design your mocks like a &lt;strong&gt;real backend&lt;/strong&gt;, with clear layers and responsibilities.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏗 The Layered Mock Architecture
&lt;/h2&gt;

&lt;p&gt;Here’s the folder structure we’ll use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  mocks/
    handlers/
      driversHandlers.ts
      ridesHandlers.ts
    factories/
      userFactory.ts
      driversFactory.ts
      vehiclesFactory.ts
      walletFactory.ts
      myLocationsFactory.ts
      myLastTripsFactory.ts
    generators/
      carLocationsGenerator.ts
      rideRequestsGenerator.ts
      priceEstimatesGenerator.ts
      routesGenerator.ts
    services/
      ridesService.ts
      driversService.ts
      walletService.ts
    browser.ts
    server.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each layer has a specific purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;factories/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Static seed data&lt;/td&gt;
&lt;td&gt;Acts as your “mock database”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generators/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dynamic or computed data&lt;/td&gt;
&lt;td&gt;Produces live, random, or rule-based data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;services/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Business logic&lt;/td&gt;
&lt;td&gt;Simulates backend operations (search, filters, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;handlers/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API interface&lt;/td&gt;
&lt;td&gt;Connects MSW routes to your mock services&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧱 Step 1: Factories — The Mock Database
&lt;/h2&gt;

&lt;p&gt;Factories provide &lt;strong&gt;static, consistent seed data&lt;/strong&gt;.&lt;br&gt;
They act like an in-memory database for your mocks.&lt;/p&gt;

&lt;p&gt;Here’s a reusable base factory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// factories/BaseFactory.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;structuredClone&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;structuredClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;createMany&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;createOne&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has no seed data`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, define your domain factories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// factories/driversFactory.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BaseFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./BaseFactory&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DriversFactory&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;vehicleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.9&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;vehicleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.7&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other factories might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;UserFactory&lt;/code&gt; – the logged-in user data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VehiclesFactory&lt;/code&gt; – registered vehicles&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WalletFactory&lt;/code&gt; – balance and transactions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MyLocationsFactory&lt;/code&gt; – user’s saved addresses&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MyLastTripsFactory&lt;/code&gt; – trip history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Tip:&lt;/strong&gt; Keep this data simple and clean. It doesn’t need to be “real” — just realistic.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Step 2: Generators — Dynamic or Computed Data
&lt;/h2&gt;

&lt;p&gt;Some data can’t be static. Think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A driver’s &lt;strong&gt;live location&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price estimates&lt;/strong&gt; that change with distance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes&lt;/strong&gt; generated from coordinates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s where &lt;strong&gt;generators&lt;/strong&gt; come in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// generators/carLocationsGenerator.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@faker-js/faker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateCarLocations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;driverId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can build similar ones for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rideRequestsGenerator&lt;/code&gt; – mock incoming ride requests&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;priceEstimatesGenerator&lt;/code&gt; – calculate approximate fares&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;routesGenerator&lt;/code&gt; – fake polyline routes between points&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Why it matters:&lt;/strong&gt;&lt;br&gt;
Generators make your mocks feel &lt;em&gt;alive&lt;/em&gt;, perfect for testing live maps, dynamic UI updates, or ride-status screens.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 Step 3: Services — Mock Backend Logic
&lt;/h2&gt;

&lt;p&gt;Services combine factories and generators into &lt;strong&gt;domain-specific logic&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// services/ridesService.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyLastTripsFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../factories/myLastTripsFactory&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateRideRequests&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../generators/rideRequestsGenerator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generatePriceEstimates&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../generators/priceEstimatesGenerator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RidesService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyLastTripsFactory&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;createMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;listMyTrips&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;trip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;trip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getActiveRideRequests&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;generateRideRequests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getPriceEstimate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pickup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropoff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;generatePriceEstimates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pickup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropoff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Why it matters:&lt;/strong&gt;&lt;br&gt;
This mirrors how a real backend behaves — filtering, calculating, and combining data logically — not just serving static JSON.&lt;/p&gt;


&lt;h2&gt;
  
  
  🌐 Step 4: Handlers — The MSW API Layer
&lt;/h2&gt;

&lt;p&gt;Now we wire everything together using &lt;strong&gt;Mock Service Worker (MSW)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// handlers/ridesHandlers.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RidesService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/ridesService&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ridesService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RidesService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ridesHandlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/trips&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ridesService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listMyTrips&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trips&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;

  &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/price-estimate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pickup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pickup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dropoff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dropoff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ridesService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPriceEstimate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pickup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropoff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And connect it to your dev environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mocks/browser.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupWorker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ridesHandlers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./handlers/ridesHandlers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;driversHandlers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./handlers/driversHandlers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setupWorker&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;ridesHandlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;driversHandlers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start it automatically in dev mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEV&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./mocks/browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;onUnhandledRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bypass&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧰 Bonus: Works in Tests and Storybook Too
&lt;/h2&gt;

&lt;p&gt;This architecture is not just for local development — it also powers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit/Integration Tests&lt;/strong&gt; (via &lt;code&gt;setupServer&lt;/code&gt; from &lt;code&gt;msw/node&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storybook&lt;/strong&gt; (via &lt;code&gt;msw-storybook-addon&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-End Prototyping&lt;/strong&gt; without a real backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Storybook config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mswDecorator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw-storybook-addon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decorators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mswDecorator&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🌱 Why This Architecture Works
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🧩 &lt;strong&gt;Separation of Concerns&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Each layer (factory, generator, service) does one job&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚙️ &lt;strong&gt;Backend-Like Simulation&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Services handle filtering, routes, and price logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔁 &lt;strong&gt;Reusability&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Works in dev, tests, and Storybook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💡 &lt;strong&gt;Flexibility&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Add or override scenarios easily (e.g., surge pricing, no drivers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧱 &lt;strong&gt;Maintainability&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Add new entities (e.g., Wallet, Vehicles) without rewriting mocks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ Conclusion
&lt;/h2&gt;

&lt;p&gt;This architecture gives you &lt;strong&gt;production-like realism&lt;/strong&gt; without depending on real APIs.&lt;br&gt;
Your frontend becomes faster to develop, test, and demo — even before the backend exists.&lt;/p&gt;

&lt;p&gt;By organizing your mocks into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧱 &lt;strong&gt;Factories&lt;/strong&gt; (static seeds)&lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Generators&lt;/strong&gt; (dynamic data)&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Services&lt;/strong&gt; (logic layer)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and connecting them through MSW handlers, you create a &lt;strong&gt;self-contained virtual backend&lt;/strong&gt; for your app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This example used Uber-like entities such as &lt;em&gt;Drivers&lt;/em&gt;, &lt;em&gt;Vehicles&lt;/em&gt;, &lt;em&gt;MyLocations&lt;/em&gt;, &lt;em&gt;Wallet&lt;/em&gt;, and &lt;em&gt;RideRequests&lt;/em&gt;, but the same pattern applies to any complex domain — e-commerce, fintech, IoT, you name it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Click the links below to follow me on all platforms:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/mrajaeim" rel="noopener noreferrer"&gt;Connect on LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
📝 &lt;strong&gt;&lt;a href="https://medium.com/@mrajaeim" rel="noopener noreferrer"&gt;Follow on Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
💻 &lt;strong&gt;&lt;a href="https://dev.to/mrajaeim"&gt;Follow on Dev.to&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

</description>
      <category>frontend</category>
      <category>testing</category>
      <category>react</category>
      <category>vue</category>
    </item>
    <item>
      <title>A Guide to Modern Browser Storage And Data Sharing Capabilities</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Thu, 16 Oct 2025 20:54:50 +0000</pubDate>
      <link>https://dev.to/mrajaeim/a-guide-to-modern-browser-storage-and-data-sharing-capabilities-4eb8</link>
      <guid>https://dev.to/mrajaeim/a-guide-to-modern-browser-storage-and-data-sharing-capabilities-4eb8</guid>
      <description>&lt;p&gt;&lt;strong&gt;Choosing the right browser storage can make or break your app's performance and security—here's how to get it right.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the early days of the web, browsers were simple document viewers. Today, they are powerful application platforms. Modern web apps often feel as responsive and capable as their native counterparts, and a key reason for this is their ability to store data directly on the client-side. But with great power comes great responsibility. The choice of where and how you store data in the browser has profound implications for your application's user experience, security, and overall performance.&lt;/p&gt;

&lt;p&gt;It's a common pitfall to reach for a familiar tool like &lt;code&gt;localStorage&lt;/code&gt; for every problem, but not all storage mechanisms are created equal. Some are synchronous, blocking the main thread and creating a janky user experience. Others are asynchronous and scalable but come with a steeper learning curve. Some are vulnerable to cross-site scripting (XSS) attacks, while others offer a more secure, sandboxed environment. Making the wrong choice can lead to anything from a sluggish UI to a critical security breach.&lt;/p&gt;

&lt;p&gt;This article is a practical guide to navigating the complex landscape of modern browser storage. We'll move beyond the familiar &lt;code&gt;localStorage&lt;/code&gt; and explore the full spectrum of tools at your disposal, including &lt;code&gt;SessionStorage&lt;/code&gt;, &lt;code&gt;Cookies&lt;/code&gt;, &lt;code&gt;IndexedDB&lt;/code&gt;, &lt;code&gt;Service Workers&lt;/code&gt;, and more. For each, we'll analyze the critical trade-offs between performance and security, and establish clear best practices. By the end, you'll be equipped to choose the right storage for the right job, building faster, more secure, and more reliable web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
The Classics: localstorage, sessionstorage, and cookies

&lt;ul&gt;
&lt;li&gt;LocalStorage: The Persistent Key-Value Store&lt;/li&gt;
&lt;li&gt;SessionStorage: The Tab-Specific Store&lt;/li&gt;
&lt;li&gt;Cookies: The Server's Messenger&lt;/li&gt;
&lt;li&gt;Quick Comparison: The Classics&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
The Modern Powerhouse: raw-indexeddb-endraw

&lt;ul&gt;
&lt;li&gt;Performance: Asynchronous and Scalable&lt;/li&gt;
&lt;li&gt;Security: Origin-Isolated with Potential for More&lt;/li&gt;
&lt;li&gt;The Catch: A Complex API&lt;/li&gt;
&lt;li&gt;Best Practices: Use a Wrapper!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Specialized Tools for Specific Jobs

&lt;ul&gt;
&lt;li&gt;In-Memory Storage: The Need for Speed&lt;/li&gt;
&lt;li&gt;URL Query Parameters: The Shareable State&lt;/li&gt;
&lt;li&gt;BroadcastChannel API: The Cross-Tab Communicator&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Powering Offline Experiences: Service Workers and the Cache API

&lt;ul&gt;
&lt;li&gt;The Service Worker: Your App's Network Proxy&lt;/li&gt;
&lt;li&gt;The Cache API: The Service Worker's Storage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Tying It All Together: Comparison and Best Practices

&lt;ul&gt;
&lt;li&gt;At a Glance: A Comparison of Browser Storage&lt;/li&gt;
&lt;li&gt;Unified Best Practices&lt;/li&gt;
&lt;li&gt;Key Takeaways&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Conclusion: Build Smarter, Not Harder&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Classics: &lt;code&gt;LocalStorage&lt;/code&gt;, &lt;code&gt;SessionStorage&lt;/code&gt;, and &lt;code&gt;Cookies&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before we dive into the heavy-duty storage solutions, let's revisit the three tools that have been the bedrock of browser data persistence for years. While still useful in specific scenarios, their limitations are what drove the need for more modern APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;LocalStorage&lt;/code&gt;: The Persistent Key-Value Store
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;LocalStorage&lt;/code&gt; is often the first tool developers reach for when they need to save data across browser sessions. It offers a simple, synchronous API for storing key-value pairs as strings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: The biggest drawback of &lt;code&gt;LocalStorage&lt;/code&gt; is its &lt;strong&gt;synchronous API&lt;/strong&gt;. Every read or write operation blocks the main thread, which can lead to a frozen UI if you're working with large amounts of data. With a typical limit of 5-10 MB, it's easy to run into performance bottlenecks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Data in &lt;code&gt;LocalStorage&lt;/code&gt; is accessible to any JavaScript running on the same origin. This makes it a prime target for &lt;strong&gt;Cross-Site Scripting (XSS) attacks&lt;/strong&gt;. If a malicious script finds its way onto your page, it can read everything in &lt;code&gt;LocalStorage&lt;/code&gt;. For this reason, you should &lt;strong&gt;never store sensitive information&lt;/strong&gt; like JWTs, API keys, or personal user data here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Non-sensitive, infrequently updated data, such as user interface preferences (like a theme choice) or remembering that a welcome modal has been closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SessionStorage&lt;/code&gt;: The Tab-Specific Store
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SessionStorage&lt;/code&gt; is nearly identical to &lt;code&gt;LocalStorage&lt;/code&gt; in its API, with one critical difference: its scope. Data stored in &lt;code&gt;SessionStorage&lt;/code&gt; is isolated to the current browser tab and is cleared the moment the tab is closed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance &amp;amp; Security&lt;/strong&gt;: It shares the same synchronous, blocking API and XSS vulnerabilities as &lt;code&gt;LocalStorage&lt;/code&gt;. The tab-specific isolation provides a minor security benefit by preventing scripts in other tabs from accessing the data, but the core risks remain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Storing transient data related to a single user session within one tab. A classic example is saving partially filled form data to prevent loss on an accidental reload.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Cookies&lt;/code&gt;: The Server's Messenger
&lt;/h3&gt;

&lt;p&gt;Unlike &lt;code&gt;LocalStorage&lt;/code&gt; and &lt;code&gt;SessionStorage&lt;/code&gt;, cookies were designed primarily for server-client communication, not client-side storage. They are automatically sent with every HTTP request to the same domain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Because they are attached to every request, large cookies can bloat request headers and slow down your application. Their small size limit (around 4KB) also makes them unsuitable for storing any significant amount of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Cookies are the traditional way to manage user sessions, but they come with their own set of security risks, most notably &lt;strong&gt;Cross-Site Request Forgery (CSRF)&lt;/strong&gt;. To mitigate this, modern applications must use the &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt;, and &lt;code&gt;SameSite=Strict&lt;/code&gt; attributes. The &lt;code&gt;HttpOnly&lt;/code&gt; flag is particularly important, as it makes the cookie inaccessible to JavaScript, providing a strong defense against XSS-based token theft.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Storing server-issued session identifiers. Use them for authentication tokens, but keep them small and secure them with the right flags. Avoid using them as a general-purpose data store.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick Comparison: The Classics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;LocalStorage&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;SessionStorage&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Cookies&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Until cleared by user&lt;/td&gt;
&lt;td&gt;Per tab/session&lt;/td&gt;
&lt;td&gt;Expires or session-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Origin-wide&lt;/td&gt;
&lt;td&gt;Tab-specific&lt;/td&gt;
&lt;td&gt;Domain/path specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Synchronous&lt;/td&gt;
&lt;td&gt;Synchronous&lt;/td&gt;
&lt;td&gt;N/A (sent via HTTP headers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capacity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~5-10 MB&lt;/td&gt;
&lt;td&gt;~5 MB&lt;/td&gt;
&lt;td&gt;~4 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High XSS risk&lt;/td&gt;
&lt;td&gt;High XSS risk&lt;/td&gt;
&lt;td&gt;CSRF/XSS risk (mitigable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main Use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;UI preferences&lt;/td&gt;
&lt;td&gt;Temporary form data&lt;/td&gt;
&lt;td&gt;Server authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Modern Powerhouse: &lt;code&gt;IndexedDB&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When your application's storage needs grow beyond simple key-value pairs, or when the performance cost of &lt;code&gt;LocalStorage&lt;/code&gt; becomes too high, it's time to turn to &lt;code&gt;IndexedDB&lt;/code&gt;. This is a true client-side database, offering capabilities far beyond the simple storage mechanisms we've discussed so far.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IndexedDB&lt;/code&gt; is a low-level API for client-side storage of significant amounts of structured data, including files/blobs. It's the browser's answer to the limitations of &lt;code&gt;LocalStorage&lt;/code&gt; and is the foundation for most modern, data-intensive web applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance: Asynchronous and Scalable
&lt;/h3&gt;

&lt;p&gt;The single most important feature of &lt;code&gt;IndexedDB&lt;/code&gt; is its &lt;strong&gt;asynchronous API&lt;/strong&gt;. Unlike &lt;code&gt;LocalStorage&lt;/code&gt;, operations in &lt;code&gt;IndexedDB&lt;/code&gt; do not block the main thread. This means you can read or write large amounts of data without freezing the user interface, resulting in a smooth and responsive application. It's designed for scale, with storage limits typically in the hundreds of megabytes or even gigabytes, depending on the browser and available disk space.&lt;/p&gt;

&lt;p&gt;Furthermore, &lt;code&gt;IndexedDB&lt;/code&gt; stores structured data—JavaScript objects—natively. This means you don't have the overhead of serializing and deserializing JSON for every operation, which can be a significant performance gain in applications with frequent data access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security: Origin-Isolated with Potential for More
&lt;/h3&gt;

&lt;p&gt;Like other browser storage, &lt;code&gt;IndexedDB&lt;/code&gt; is isolated by origin, which prevents other websites from accessing your data. However, it is still accessible to any JavaScript running on your page, which means it's vulnerable to XSS attacks if your application has a security flaw. &lt;/p&gt;

&lt;p&gt;For sensitive data, the best practice is to add a layer of client-side encryption. You can use the built-in &lt;code&gt;Web Crypto API&lt;/code&gt; to encrypt data before you store it in &lt;code&gt;IndexedDB&lt;/code&gt;, ensuring that even if an attacker gains access to the database, the data remains unreadable.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Catch: A Complex API
&lt;/h3&gt;

&lt;p&gt;With great power comes... a more complex API. The native &lt;code&gt;IndexedDB&lt;/code&gt; API is event-based and requires you to manage transactions, versioning, and schemas manually. It can be cumbersome to work with directly, which has led to the development of several excellent wrapper libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices: Use a Wrapper!
&lt;/h3&gt;

&lt;p&gt;For almost all use cases, it's highly recommended to use a library like &lt;strong&gt;&lt;code&gt;Dexie.js&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;idb&lt;/code&gt;&lt;/strong&gt;. These wrappers provide a clean, modern, &lt;code&gt;Promise&lt;/code&gt;-based API that handles the underlying complexity of &lt;code&gt;IndexedDB&lt;/code&gt; transactions and schema management. They make working with &lt;code&gt;IndexedDB&lt;/code&gt; feel almost as simple as working with &lt;code&gt;LocalStorage&lt;/code&gt;, while retaining all of its performance benefits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best For&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applications that need to store large amounts of structured data.&lt;/li&gt;
&lt;li&gt;Offline-first Progressive Web Apps (PWAs).&lt;/li&gt;
&lt;li&gt;Caching complex API responses to reduce network requests.&lt;/li&gt;
&lt;li&gt;Any scenario where the synchronous nature of &lt;code&gt;LocalStorage&lt;/code&gt; would cause performance issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Specialized Tools for Specific Jobs
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;IndexedDB&lt;/code&gt; is the champion of large-scale persistent storage, not all data needs to be stored in a database. Sometimes you need the fastest possible access for temporary data, a way to share state in a URL, or a method to communicate between open tabs. For these jobs, we have a set of specialized tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  In-Memory Storage: The Need for Speed
&lt;/h3&gt;

&lt;p&gt;Not all data needs to survive a page refresh. The fastest storage available is the computer's RAM, which you can access directly by storing data in JavaScript variables or more structured state management solutions like Redux or Zustand stores.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Unbeatable. Access is nearly instantaneous, with no serialization overhead. This is where your application's active state should live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Persistence&lt;/strong&gt;: Being volatile is its key feature. Since the data is wiped on every page load, the security exposure is minimal. It's perfect for data that is fetched and used in a single session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Caching frequently accessed data that can be easily re-fetched, managing the real-time state of your UI, and holding temporary data that doesn't need to be persisted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  URL Query Parameters: The Shareable State
&lt;/h3&gt;

&lt;p&gt;Sometimes, the state of your application needs to be shareable. Think of applying a set of filters on an e-commerce site and wanting to send the results to a friend. This is the perfect use case for URL query parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: There's no real I/O cost, but be mindful of URL length limits (generally around 2000 characters), as excessively long URLs can cause issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: This is the most public form of state. The data is visible in the user's browser history, server logs, and to anyone they share the link with. &lt;strong&gt;Never, ever put sensitive information in a URL&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Small, non-sensitive pieces of data that make a page's state shareable and bookmarkable, such as search queries, filter settings, or pagination info (&lt;code&gt;?page=2&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;BroadcastChannel&lt;/code&gt; API: The Cross-Tab Communicator
&lt;/h3&gt;

&lt;p&gt;What happens when a user logs out in one tab? Ideally, they should be logged out in all other open tabs of your application as well. This is the problem the &lt;code&gt;BroadcastChannel&lt;/code&gt; API was designed to solve.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: It's a lightweight, event-driven API that allows different browser tabs, windows, or iframes of the same origin to send and receive messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Channels are scoped to a single origin, but any script on that origin can listen in. Therefore, you should never broadcast sensitive data. Instead, send simple signals or notifications, like "user-logged-out" or "theme-changed-to-dark".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Syncing state across multiple open tabs. It's the modern, efficient way to ensure a consistent user experience, especially for actions like authentication, theme changes, or real-time notifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For more detailed information, please visit &lt;a href="https://medium.com/@mrajaeim/understanding-window-postmessage-and-window-parent-postmessage-in-javascript-f09d4eac68ba" rel="noopener noreferrer"&gt;Mastering Cross-Window Communication in JavaScript: postMessage vs BroadcastChannel Explained&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Powering Offline Experiences: Service Workers and the Cache API
&lt;/h2&gt;

&lt;p&gt;What truly separates a modern web app from a traditional website is the ability to function without a network connection. This is the domain of the &lt;strong&gt;Service Worker&lt;/strong&gt;, a powerful technology that acts as a programmable proxy between your application, the browser, and the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Service Worker: Your App's Network Proxy
&lt;/h3&gt;

&lt;p&gt;A Service Worker is a type of Web Worker that runs on a separate thread from your main application. It can intercept and handle network requests, manage a cache of responses, and enable push notifications. Because it runs independently of your UI, it can continue to work even when the user has closed the application's tab, enabling features like background sync.&lt;/p&gt;

&lt;p&gt;Service Workers are the cornerstone of Progressive Web Apps (PWAs), allowing them to provide a reliable, app-like experience even on a flaky network connection or when completely offline.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;Cache API&lt;/code&gt;: The Service Worker's Storage
&lt;/h3&gt;

&lt;p&gt;While a Service Worker can use &lt;code&gt;IndexedDB&lt;/code&gt;, its primary storage tool is the &lt;strong&gt;&lt;code&gt;Cache API&lt;/code&gt;&lt;/strong&gt;. This is a specialized storage mechanism designed for holding HTTP request and response pairs. It allows you to programmatically save network responses and serve them directly from the cache, bypassing the network entirely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: The performance implications are massive. By serving assets and API responses from the cache, you can make your application load almost instantly on repeat visits. Caching strategies like &lt;code&gt;stale-while-revalidate&lt;/code&gt; (serving from the cache while fetching an update in the background) provide the perfect balance of speed and freshness.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: Service Workers are highly secure. They can only be registered on pages served over &lt;strong&gt;HTTPS&lt;/strong&gt;, which prevents man-in-the-middle attacks. They run in a sandboxed environment and have no direct access to the DOM, which limits their exposure to XSS attacks. However, you must still be careful not to cache sensitive, user-specific data, as the cache is persistent and could be accessed if the application's security is compromised.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Best For&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating offline-first applications.&lt;/li&gt;
&lt;li&gt;Caching application shell assets (HTML, CSS, JS) for instant loading.&lt;/li&gt;
&lt;li&gt;Caching API responses to reduce network dependency and improve perceived performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tying It All Together: Comparison and Best Practices
&lt;/h2&gt;

&lt;p&gt;We've explored a wide range of browser storage options, each with its own strengths and weaknesses. Choosing the right one depends on a careful balance of performance, security, and persistence requirements. To make this easier, let's summarize our findings.&lt;/p&gt;

&lt;h3&gt;
  
  
  At a Glance: A Comparison of Browser Storage
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Storage Type&lt;/th&gt;
&lt;th&gt;Security Level&lt;/th&gt;
&lt;th&gt;Performance Impact&lt;/th&gt;
&lt;th&gt;Persistence&lt;/th&gt;
&lt;th&gt;Size Limit&lt;/th&gt;
&lt;th&gt;Async&lt;/th&gt;
&lt;th&gt;Typical Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;In-Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Secure (Volatile)&lt;/td&gt;
&lt;td&gt;⚡ Fastest&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;RAM Limit&lt;/td&gt;
&lt;td&gt;✅ N/A&lt;/td&gt;
&lt;td&gt;Temporary UI State&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LocalStorage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ High XSS Risk&lt;/td&gt;
&lt;td&gt;🚫 Blocking I/O&lt;/td&gt;
&lt;td&gt;✅ Permanent&lt;/td&gt;
&lt;td&gt;~5MB&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Non-sensitive Preferences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SessionStorage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ High XSS Risk&lt;/td&gt;
&lt;td&gt;🚫 Blocking I/O&lt;/td&gt;
&lt;td&gt;⚪ Per Tab&lt;/td&gt;
&lt;td&gt;~5MB&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Single-tab Session Data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cookies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ CSRF/XSS Risk&lt;/td&gt;
&lt;td&gt;🚫 Slows HTTP&lt;/td&gt;
&lt;td&gt;✅ Expires&lt;/td&gt;
&lt;td&gt;~4KB&lt;/td&gt;
&lt;td&gt;✅ N/A&lt;/td&gt;
&lt;td&gt;Server Session Tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IndexedDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚪ XSS Risk (Encrypt!)&lt;/td&gt;
&lt;td&gt;✅ Async, Scalable&lt;/td&gt;
&lt;td&gt;✅ Permanent&lt;/td&gt;
&lt;td&gt;100MB+&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Large/Structured Data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cache API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Sandboxed (HTTPS)&lt;/td&gt;
&lt;td&gt;✅ Async, Fast&lt;/td&gt;
&lt;td&gt;✅ Evictable&lt;/td&gt;
&lt;td&gt;Large&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Offline Assets &amp;amp; Responses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;URL Params&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Publicly Visible&lt;/td&gt;
&lt;td&gt;⚡ Light&lt;/td&gt;
&lt;td&gt;⚪ Shareable&lt;/td&gt;
&lt;td&gt;~2KB&lt;/td&gt;
&lt;td&gt;✅ N/A&lt;/td&gt;
&lt;td&gt;Shareable Filter State&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BroadcastChannel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ Cross-tab Exposure&lt;/td&gt;
&lt;td&gt;⚡ Fast (Events)&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Cross-tab Syncing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Unified Best Practices
&lt;/h3&gt;

&lt;p&gt;Regardless of the tool you choose, a few universal principles will help you build more secure and performant applications.&lt;/p&gt;

&lt;h4&gt;
  
  
  🧱 Security Principles
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never Store Sensitive Data in Client-Accessible Storage&lt;/strong&gt;: This includes JWTs, API keys, passwords, or personal information. &lt;code&gt;LocalStorage&lt;/code&gt;, &lt;code&gt;SessionStorage&lt;/code&gt;, and &lt;code&gt;IndexedDB&lt;/code&gt; are all readable by any JavaScript on the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;HttpOnly&lt;/code&gt; Cookies for Auth Tokens&lt;/strong&gt;: This is the single most effective defense against token theft via XSS, as it makes the cookie inaccessible to JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypt Sensitive Local Data&lt;/strong&gt;: If you must store sensitive information client-side (e.g., in &lt;code&gt;IndexedDB&lt;/code&gt; for an offline app), use the &lt;code&gt;Web Crypto API&lt;/code&gt; to encrypt it first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assume All Client-Side Data Can Be Manipulated&lt;/strong&gt;: Always validate data on the server before processing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚡ Performance Principles
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Async Over Sync&lt;/strong&gt;: Always prefer asynchronous APIs like &lt;code&gt;IndexedDB&lt;/code&gt; and the &lt;code&gt;Cache API&lt;/code&gt; over synchronous ones like &lt;code&gt;LocalStorage&lt;/code&gt; to avoid blocking the main thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Load Your Data&lt;/strong&gt;: Don't eagerly load large amounts of data into storage. Fetch and cache it as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use In-Memory for Hot Data&lt;/strong&gt;: For data that is accessed frequently, keep it in an in-memory state variable for the fastest possible access. Persist it to storage only when necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be Mindful of Quotas&lt;/strong&gt;: Monitor storage usage with &lt;code&gt;navigator.storage.estimate()&lt;/code&gt; and be prepared to handle quota errors gracefully.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;LocalStorage&lt;/code&gt; is not your default&lt;/strong&gt;: Its synchronous nature and security risks make it a poor choice for anything but the simplest, non-sensitive data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;IndexedDB&lt;/code&gt; is the modern standard&lt;/strong&gt;: For any significant amount of client-side data, &lt;code&gt;IndexedDB&lt;/code&gt; (used with a wrapper like &lt;code&gt;Dexie.js&lt;/code&gt;) is the best choice for performance and scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;HttpOnly&lt;/code&gt; cookies are for authentication&lt;/strong&gt;: They are the most secure place to store session tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Workers are for offline&lt;/strong&gt;: The &lt;code&gt;Cache API&lt;/code&gt; combined with a Service Worker is the key to building reliable, offline-first applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security is paramount&lt;/strong&gt;: Never trust the client. Encrypt sensitive data and use &lt;code&gt;HttpOnly&lt;/code&gt; cookies for authentication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion: Build Smarter, Not Harder
&lt;/h2&gt;

&lt;p&gt;The landscape of browser storage is far richer and more nuanced than just &lt;code&gt;localStorage&lt;/code&gt;. Choosing the right storage solution is not about finding a single tool that does everything; it's about understanding the trade-offs and composing a strategy that fits your application's unique needs. The modern web is built on a foundation of smart, hybrid approaches.&lt;/p&gt;

&lt;p&gt;An application might use &lt;code&gt;HttpOnly&lt;/code&gt; cookies for authentication, &lt;code&gt;IndexedDB&lt;/code&gt; to store complex data for offline use, in-memory variables for real-time UI state, and the &lt;code&gt;BroadcastChannel&lt;/code&gt; API to keep multiple tabs in sync. This is not over-engineering; it's a sign of a mature, robust architecture.&lt;/p&gt;

&lt;p&gt;As browsers continue to evolve, the trend is clear: we are moving towards more secure, asynchronous, and origin-isolated storage models. By embracing these modern APIs and understanding their underlying principles, you can build the next generation of web applications—apps that are not only fast and feature-rich but also secure and reliable, no matter the user's device or network condition. The power is in your hands; it's time to build smarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me on Medium, Dev.to, and LinkedIn! 🚀😊
&lt;/h2&gt;

&lt;p&gt;Your support and engagement mean the world to me.&lt;br&gt;&lt;br&gt;
Let's create a community of knowledge enthusiasts and professionals striving for excellence and continuous learning.  &lt;/p&gt;

&lt;p&gt;Click the links below to follow me on all platforms:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/mrajaeim" rel="noopener noreferrer"&gt;Connect on LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
📝 &lt;strong&gt;&lt;a href="https://medium.com/@mrajaeim" rel="noopener noreferrer"&gt;Follow on Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
💻 &lt;strong&gt;&lt;a href="https://dev.to/mrajaeim"&gt;Follow on Dev.to&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;#WebSecurity&lt;/code&gt; &lt;code&gt;#WebPerformance&lt;/code&gt; &lt;code&gt;#WebDevelopment&lt;/code&gt; &lt;code&gt;#BrowserAPIs&lt;/code&gt; &lt;code&gt;#Frontend&lt;/code&gt; &lt;code&gt;#JavaScript&lt;/code&gt; &lt;code&gt;#IndexedDB&lt;/code&gt; &lt;code&gt;#Cookies&lt;/code&gt; &lt;code&gt;#LocalStorage&lt;/code&gt; &lt;code&gt;#PWAs&lt;/code&gt; &lt;code&gt;#WebDevTips&lt;/code&gt;&lt;/p&gt;

</description>
      <category>websecurity</category>
      <category>webperf</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The Ultimate Guide to Mastering `useEffect`</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Wed, 15 Oct 2025 14:24:38 +0000</pubDate>
      <link>https://dev.to/mrajaeim/the-ultimate-guide-to-mastering-useeffect-1ci9</link>
      <guid>https://dev.to/mrajaeim/the-ultimate-guide-to-mastering-useeffect-1ci9</guid>
      <description>&lt;p&gt;From lifecycle chaos to declarative harmony, this guide demystifies React's most powerful Hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; Hook is arguably one of the most important yet misunderstood parts of modern React. For developers coming from class-based components, it feels like a strange new paradigm. For newcomers, it can seem like a magic box where you put any code that "doesn't fit" in the render. But &lt;code&gt;useEffect&lt;/code&gt; is far more than that—it's a precise tool for synchronizing your component with external systems.&lt;/p&gt;

&lt;p&gt;This guide breaks down everything you need to know, from the fundamentals of component lifecycles to advanced patterns and common pitfalls. By the end, you'll not only understand &lt;em&gt;how&lt;/em&gt; &lt;code&gt;useEffect&lt;/code&gt; works but also &lt;em&gt;why&lt;/em&gt; it was designed and &lt;em&gt;when&lt;/em&gt; to use it effectively. Let's dive in and transform &lt;code&gt;useEffect&lt;/code&gt; from a source of confusion into your most reliable ally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
1. Understanding the React Component Lifecycle

&lt;ul&gt;
&lt;li&gt;Before Hooks: The Classic Lifecycle Methods&lt;/li&gt;
&lt;li&gt;After Hooks: &lt;code&gt;useEffect&lt;/code&gt; Unifies the Lifecycle&lt;/li&gt;
&lt;li&gt;A Visual Timeline of the Functional Component Lifecycle&lt;/li&gt;
&lt;li&gt;Why Was &lt;code&gt;useEffect&lt;/code&gt; Introduced?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
2. The Purpose of &lt;code&gt;useEffect&lt;/code&gt; — What It Really Does

&lt;ul&gt;
&lt;li&gt;Common Examples of Side Effects&lt;/li&gt;
&lt;li&gt;It Runs After the Paint&lt;/li&gt;
&lt;li&gt;Misconception: It’s Not for All Logic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
3. The Dependencies Array Demystified

&lt;ul&gt;
&lt;li&gt;The Three Modes of &lt;code&gt;useEffect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;How React Compares Dependencies&lt;/li&gt;
&lt;li&gt;How to Fix Shallow Comparison Issues&lt;/li&gt;
&lt;li&gt;Tips to Avoid Common Pitfalls&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
4. Cleanup Functions and the “Return” Mystery

&lt;ul&gt;
&lt;li&gt;Why &lt;code&gt;useEffect&lt;/code&gt; Can Return a Function&lt;/li&gt;
&lt;li&gt;When Does the Cleanup Function Run?&lt;/li&gt;
&lt;li&gt;Real-World Cases for Cleanup&lt;/li&gt;
&lt;li&gt;Why Cleanup Prevents Memory Leaks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
5. Multiple &lt;code&gt;useEffect&lt;/code&gt;s: Execution and Cleanup Order

&lt;ul&gt;
&lt;li&gt;Execution Order: Top to Bottom&lt;/li&gt;
&lt;li&gt;Cleanup Order: Bottom to Top (Reverse Order)&lt;/li&gt;
&lt;li&gt;Why Splitting Concerns is Cleaner&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
6. Debugging &lt;code&gt;useEffect&lt;/code&gt; Like a Pro

&lt;ul&gt;
&lt;li&gt;Common Pitfalls and How to Spot Them&lt;/li&gt;
&lt;li&gt;Use the ESLint Rule (and When to Ignore It)&lt;/li&gt;
&lt;li&gt;Tracing with Logs and Custom Hooks&lt;/li&gt;
&lt;li&gt;React DevTools Profiler&lt;/li&gt;
&lt;li&gt;Tips: &lt;code&gt;useRef&lt;/code&gt; for Tracking&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
7. When Not to Use &lt;code&gt;useEffect&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Anti-Pattern: Unnecessary State Mirroring&lt;/li&gt;
&lt;li&gt;Anti-Pattern: Computations and Derived State&lt;/li&gt;
&lt;li&gt;Prefer Event Handlers for User Actions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
8. Practical Examples &amp;amp; Patterns

&lt;ul&gt;
&lt;li&gt;Pattern: Data Fetching with &lt;code&gt;AbortController&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pattern: Syncing the Browser Tab Title&lt;/li&gt;
&lt;li&gt;Pattern: Custom Hooks Abstraction (e.g., &lt;code&gt;useLocalStorage&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
9. Wrap-Up

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useEffect&lt;/code&gt; Cheat Sheet&lt;/li&gt;
&lt;li&gt;Visual Summary&lt;/li&gt;
&lt;li&gt;The Future of Effects&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Follow Me on Medium, Dev.to, and LinkedIn! 🚀😊&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Understanding the React Component Lifecycle
&lt;/h2&gt;

&lt;p&gt;Before we can master &lt;code&gt;useEffect&lt;/code&gt;, we need to travel back in time to the era of class components. The component lifecycle was a set of distinct methods that gave us hooks into a component's life, from birth to death.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before Hooks: The Classic Lifecycle Methods
&lt;/h3&gt;

&lt;p&gt;In class components, side effects like fetching data, setting up subscriptions, or manually changing the DOM were handled by specific lifecycle methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidMount()&lt;/code&gt;&lt;/strong&gt;: Fired only once, immediately after the component is mounted (inserted into the tree). This was the perfect place for initial data fetches or setting up subscriptions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidUpdate(prevProps, prevState)&lt;/code&gt;&lt;/strong&gt;: Called on every re-render, but not for the initial render. Logic here often required checking if props or state had changed to avoid unnecessary re-fetches.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentWillUnmount()&lt;/code&gt;&lt;/strong&gt;: Called right before the component is destroyed. This was the place to clean up subscriptions, timers, or any other lingering side effects to prevent memory leaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation often led to related logic being split across different methods, making components harder to follow.&lt;/p&gt;

&lt;h3&gt;
  
  
  After Hooks: &lt;code&gt;useEffect&lt;/code&gt; Unifies the Lifecycle
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; Hook simplifies this by unifying these concepts into a single API. It runs &lt;em&gt;after&lt;/em&gt; React renders the component, allowing you to perform side effects without blocking the browser paint.&lt;/p&gt;

&lt;p&gt;Here’s how it maps to the old lifecycle methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidMount&lt;/code&gt;&lt;/strong&gt;: An effect with an empty dependency array (&lt;code&gt;[]&lt;/code&gt;) runs only once, after the initial render.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidUpdate&lt;/code&gt;&lt;/strong&gt;: An effect with dependencies in its array (&lt;code&gt;[prop, state]&lt;/code&gt;) runs after the initial render and any time those dependencies change.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentWillUnmount&lt;/code&gt;&lt;/strong&gt;: The cleanup function returned from an effect serves this purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This new model encourages you to group related logic together, not by lifecycle event, but by &lt;strong&gt;concern&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Visual Timeline of the Functional Component Lifecycle
&lt;/h3&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%2Fogdi2xc66acroyfqmgdg.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%2Fogdi2xc66acroyfqmgdg.png" alt=" " width="523" height="637"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Why Was &lt;code&gt;useEffect&lt;/code&gt; Introduced?
&lt;/h3&gt;

&lt;p&gt;The shift to Hooks wasn't just for a cleaner syntax. It solved fundamental problems with class components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Separation of Concerns&lt;/strong&gt;: In classes, a single &lt;code&gt;componentDidMount&lt;/code&gt; might contain logic for data fetching, setting up event listeners, and logging. &lt;code&gt;useEffect&lt;/code&gt; allows you to split these into separate, independent effects. Each effect handles one concern, making the code more modular and readable.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Declarative Side Effects&lt;/strong&gt;: Instead of issuing imperative commands at different points in time (&lt;code&gt;mount&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;), you &lt;em&gt;declare&lt;/em&gt; the side effects that should be synchronized with your component's state. You tell React, “When this data changes, run this effect.” React handles the when and how, making your code less error-prone and easier to reason about.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  2. The Purpose of &lt;code&gt;useEffect&lt;/code&gt; — What It Really Does
&lt;/h2&gt;

&lt;p&gt;The official React documentation defines &lt;code&gt;useEffect&lt;/code&gt; as a way to perform side effects in function components. But what exactly is a “side effect”?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; A side effect is any interaction with the “outside world” that occurs outside of a component’s render. If your component is a pure function, its only job is to return JSX based on its props and state. Anything else is a side effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Examples of Side Effects
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is your go-to tool for managing these interactions. Here are the most common use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Fetching data from an API&lt;/strong&gt;: Retrieving remote data and updating component state.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Setting up subscriptions&lt;/strong&gt;: Connecting to a WebSocket or listening to a real-time service.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Manual DOM manipulation&lt;/strong&gt;: Directly changing the DOM, like focusing an input field or integrating with a non-React library.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Logging&lt;/strong&gt;: Sending analytics or error reports to a logging service.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Using browser APIs&lt;/strong&gt;: Interacting with &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;Cookies&lt;/code&gt;, &lt;code&gt;document.title&lt;/code&gt;, or timers like &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;setInterval&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  It Runs &lt;em&gt;After&lt;/em&gt; the Paint
&lt;/h3&gt;

&lt;p&gt;A critical detail that often trips up developers is &lt;em&gt;when&lt;/em&gt; &lt;code&gt;useEffect&lt;/code&gt; runs. Unlike &lt;code&gt;componentDidMount&lt;/code&gt; and &lt;code&gt;componentDidUpdate&lt;/code&gt;, which could block the browser from painting, &lt;code&gt;useEffect&lt;/code&gt; is deferred. It runs &lt;em&gt;after&lt;/em&gt; React has rendered your component and the browser has painted the result to the screen.&lt;/p&gt;

&lt;p&gt;This is a huge performance benefit. It ensures that side effects, which can be slow, don't make your UI feel sluggish. The user sees the updated UI first, and then the effect runs in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misconception: It’s Not for All Logic
&lt;/h3&gt;

&lt;p&gt;Because &lt;code&gt;useEffect&lt;/code&gt; is so versatile, it's tempting to put any and all logic inside it. This is a common anti-pattern. &lt;code&gt;useEffect&lt;/code&gt; is for synchronizing with external systems. If you can calculate a value or derive state directly during the render, you don't need an effect. Using it for simple computations adds unnecessary complexity and can lead to bugs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rule of Thumb:&lt;/strong&gt; If your logic doesn't interact with the outside world, it probably doesn't belong in &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. The Dependencies Array Demystified
&lt;/h2&gt;

&lt;p&gt;The second argument to &lt;code&gt;useEffect&lt;/code&gt; is the dependencies array. This array is the key to controlling &lt;em&gt;when&lt;/em&gt; your effect runs. Get it right, and your components will be efficient and predictable. Get it wrong, and you'll face bugs like infinite loops and stale data.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Three Modes of &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can think of the dependency array as having three primary modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Dependency Array:&lt;/strong&gt; &lt;code&gt;useEffect(() =&amp;gt; { ... })&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;When it runs&lt;/strong&gt;: After the initial render and &lt;em&gt;every single re-render&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why it's often bad&lt;/strong&gt;: This can be inefficient and dangerous. If the effect triggers a state update, it will cause a re-render, which will trigger the effect again, leading to an infinite loop. Use this mode with extreme caution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Empty Array:&lt;/strong&gt; &lt;code&gt;useEffect(() =&amp;gt; { ... }, [])&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;When it runs&lt;/strong&gt;: Only once, after the initial render.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;This is the equivalent of &lt;code&gt;componentDidMount&lt;/code&gt;&lt;/strong&gt;. It’s perfect for one-time setup logic, like fetching initial data or setting up a subscription that doesn't depend on any props or state.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Array with Dependencies:&lt;/strong&gt; &lt;code&gt;useEffect(() =&amp;gt; { ... }, [prop1, stateValue])&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;When it runs&lt;/strong&gt;: After the initial render and any time a value in the dependency array changes.&lt;/li&gt;
&lt;li&gt;  This is the most common and powerful mode. It lets you synchronize your component with a specific piece of data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How React Compares Dependencies
&lt;/h3&gt;

&lt;p&gt;React performs a &lt;strong&gt;shallow comparison&lt;/strong&gt; of the items in the dependency array. It checks if &lt;code&gt;oldValue === newValue&lt;/code&gt; for each dependency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For &lt;strong&gt;primitive values&lt;/strong&gt; (strings, numbers, booleans), this works as you'd expect. &lt;code&gt;5 === 5&lt;/code&gt; is true, but &lt;code&gt;5 === 6&lt;/code&gt; is false.&lt;/li&gt;
&lt;li&gt;  For &lt;strong&gt;reference values&lt;/strong&gt; (objects, arrays, functions), it checks if the reference itself has changed, not the contents. A new object or array is created on every render, so &lt;code&gt;{} !== {}&lt;/code&gt;. This is a classic source of infinite loops.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ⚠️ Anti-pattern: This will cause an infinite loop!&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setOptions&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Some logic&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// `options` is a new object on every render&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Fix Shallow Comparison Issues
&lt;/h3&gt;

&lt;p&gt;So, how do you depend on an object or array without causing an infinite loop? Here are the recommended solutions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Memoize the Dependency with &lt;code&gt;useMemo&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need to depend on an object or array that is calculated during render, wrap it in &lt;code&gt;useMemo&lt;/code&gt;. This ensures that the object's reference only changes when its own underlying dependencies change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Memoize the object&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;filterSettings&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// `options` will only be a new object when `filterSettings` changes&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filterSettings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;includeDrafts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filterSettings&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This effect now only runs when `options` actually changes&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Depend on Primitive Values&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The simplest solution is often the best. If your effect only needs a few properties from an object, depend on those properties directly. Primitives are compared by value, so this is always safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Depend on the primitive value&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`User ID is: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Depend on `user.id`, not the whole `user` object&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Other Advanced Solutions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;JSON.stringify&lt;/code&gt;&lt;/strong&gt;: As a quick fix, you can serialize the object into a string: &lt;code&gt;[JSON.stringify(options)]&lt;/code&gt;. This works but can be inefficient for large objects and may not handle all edge cases (like key order).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deep Comparison Hooks&lt;/strong&gt;: You can find or create a custom hook (e.g., &lt;code&gt;useDeepCompareEffect&lt;/code&gt;) that uses a utility like &lt;code&gt;lodash.isEqual&lt;/code&gt; to perform a deep comparison instead of a shallow one. This is a powerful but often unnecessary abstraction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tips to Avoid Common Pitfalls
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Stale Closures&lt;/strong&gt;: If you use a state variable or prop inside an effect but forget to include it in the dependency array, the effect will “close over” the initial value of that variable. It will never see the updated value, leading to bugs. The &lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt; package is essential for catching this.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Infinite Loops&lt;/strong&gt;: Always be careful with objects, arrays, and functions in the dependency array. If you must use them, ensure they are stable between renders. Use &lt;code&gt;useCallback&lt;/code&gt; for functions and &lt;code&gt;useMemo&lt;/code&gt; for objects/arrays to memoize them.
&amp;gt; &lt;strong&gt;Pro Tip:&lt;/strong&gt; If your effect doesn't use any props or state, give it an empty dependency array &lt;code&gt;[]&lt;/code&gt;. If it does, include every one of them in the array. Let the linter guide you.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Cleanup Functions and the “Return” Mystery
&lt;/h2&gt;

&lt;p&gt;Many side effects need to be undone. If you set up a subscription, you need to unsubscribe. If you start a timer, you need to clear it. This is where the &lt;code&gt;useEffect&lt;/code&gt; cleanup function comes in. It’s the &lt;code&gt;componentWillUnmount&lt;/code&gt; of the Hooks world, but much more powerful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why &lt;code&gt;useEffect&lt;/code&gt; Can Return a Function
&lt;/h3&gt;

&lt;p&gt;If you return a function from your &lt;code&gt;useEffect&lt;/code&gt; callback, React will store it and run it at the appropriate time. This design is brilliant because it keeps the logic for setting up and tearing down an effect right next to each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// The effect logic: runs after every render where dependencies change&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Timer fired!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// The cleanup function: returned by the effect&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Clearing timer...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// Empty array means this effect runs once&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When Does the Cleanup Function Run?
&lt;/h3&gt;

&lt;p&gt;This is a key point of confusion. The cleanup function runs in two scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Before the effect runs again&lt;/strong&gt;: If your dependencies change and the effect is about to re-run, React first runs the cleanup function from the &lt;em&gt;previous&lt;/em&gt; render. This ensures you don't have multiple subscriptions or timers running at once.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;On unmount&lt;/strong&gt;: When the component is removed from the DOM, React runs the cleanup function from the &lt;em&gt;last&lt;/em&gt; render.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This behavior ensures that your effects are always cleaned up, preventing what are sometimes called “zombie effects”—lingering side effects from a component that is no longer on the screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Cases for Cleanup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Clearing timeouts or intervals&lt;/strong&gt;: As shown above, &lt;code&gt;clearTimeout&lt;/code&gt; and &lt;code&gt;clearInterval&lt;/code&gt; are essential to prevent timers from firing after a component has unmounted.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Unsubscribing from events or sockets&lt;/strong&gt;: If you use &lt;code&gt;addEventListener&lt;/code&gt; or connect to a WebSocket, you must remove the listener or close the connection to avoid memory leaks and unnecessary processing.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Canceling pending requests&lt;/strong&gt;: For data fetching, you can use an &lt;code&gt;AbortController&lt;/code&gt; to cancel a network request if the component unmounts or the dependencies change before the request completes. This prevents you from trying to update the state of an unmounted component.&lt;/li&gt;
&lt;/ul&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%2Fh82662466voezcbl9beg.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%2Fh82662466voezcbl9beg.png" alt=" " width="799" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Cleanup Prevents Memory Leaks
&lt;/h3&gt;

&lt;p&gt;Without cleanup, your application would slowly degrade. Event listeners would pile up, subscriptions would remain active, and timers would fire unexpectedly, all consuming memory and CPU cycles for components that no longer exist. The &lt;code&gt;useEffect&lt;/code&gt; cleanup function provides a simple, reliable pattern to keep your application healthy and performant.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Multiple &lt;code&gt;useEffect&lt;/code&gt;s: Execution and Cleanup Order
&lt;/h2&gt;

&lt;p&gt;A single component can have multiple &lt;code&gt;useEffect&lt;/code&gt; hooks. This is a powerful feature for separating unrelated logic. But when you have more than one, it's important to understand the order in which they run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution Order: Top to Bottom
&lt;/h3&gt;

&lt;p&gt;React executes &lt;code&gt;useEffect&lt;/code&gt; hooks in the same order they are declared in your component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First effect runs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second effect runs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Console output on mount:&lt;/span&gt;
&lt;span class="c1"&gt;// "First effect runs"&lt;/span&gt;
&lt;span class="c1"&gt;// "Second effect runs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This predictable, top-to-bottom order allows you to orchestrate side effects that might depend on each other, although it's generally better to keep them independent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleanup Order: Bottom to Top (Reverse Order)
&lt;/h3&gt;

&lt;p&gt;Here's the interesting part: the cleanup functions run in the &lt;strong&gt;reverse order&lt;/strong&gt; of the effects. When the component unmounts (or before a re-run), React will clean up the second effect, then the first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First effect setup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First effect cleanup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second effect setup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second effect cleanup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// On mount:&lt;/span&gt;
&lt;span class="c1"&gt;// "First effect setup"&lt;/span&gt;
&lt;span class="c1"&gt;// "Second effect setup"&lt;/span&gt;

&lt;span class="c1"&gt;// On unmount:&lt;/span&gt;
&lt;span class="c1"&gt;// "Second effect cleanup"&lt;/span&gt;
&lt;span class="c1"&gt;// "First effect cleanup"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it like a stack: the last effect that was set up is the first one to be torn down. This LIFO (Last-In, First-Out) order ensures that dependencies are cleaned up correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Splitting Concerns is Cleaner
&lt;/h3&gt;

&lt;p&gt;The ability to use multiple &lt;code&gt;useEffect&lt;/code&gt; hooks is the primary reason Hooks are so good at promoting separation of concerns. Instead of a monolithic &lt;code&gt;componentDidMount&lt;/code&gt; that does everything, you can have a dedicated effect for each piece of side-effect logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Separating Data Fetching from UI Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you need to fetch data and also update the document title based on that data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;postId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPost&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Effect 1: Handles data fetching&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Cleanup for this effect&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Effect 2: Handles updating the document title&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Runs only when the `post` state changes&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is incredibly clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first effect is solely responsible for fetching data. Its dependency is &lt;code&gt;postId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The second effect is solely responsible for a UI side effect (updating the title). Its dependency is &lt;code&gt;post&lt;/code&gt;.
The two pieces of logic are completely decoupled.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Debugging &lt;code&gt;useEffect&lt;/code&gt; Like a Pro
&lt;/h2&gt;

&lt;p&gt;Even with a solid understanding, &lt;code&gt;useEffect&lt;/code&gt; can still be a source of bugs. Knowing how to debug it effectively is a superpower. Here are common issues and how to solve them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Pitfalls and How to Spot Them
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Infinite Loops&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Symptom&lt;/strong&gt;: Your app becomes unresponsive, the fan kicks on, and the browser might crash.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cause&lt;/strong&gt;: An effect is updating state, which causes a re-render, which triggers the effect again. This usually happens when a dependency is an object, array, or function that is re-created on every render.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fix&lt;/strong&gt;: Memoize reference-type dependencies with &lt;code&gt;useMemo&lt;/code&gt; or &lt;code&gt;useCallback&lt;/code&gt;. For state updates, use the functional update form (&lt;code&gt;setState(prev =&amp;gt; ...)&lt;/code&gt;), which can sometimes remove the need to depend on the state itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Missing Dependencies&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Symptom&lt;/strong&gt;: The effect doesn't re-run when you expect it to. Data becomes stale.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cause&lt;/strong&gt;: You used a prop or state variable inside the effect but didn't add it to the dependency array. The effect has a "stale closure" over the old value.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fix&lt;/strong&gt;: Turn on the &lt;code&gt;react-hooks/exhaustive-deps&lt;/code&gt; ESLint rule. It's your best friend for catching this. Trust the linter; it's almost always right.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stale State in Async Operations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Symptom&lt;/strong&gt;: An async function (like a &lt;code&gt;setTimeout&lt;/code&gt; callback) reads a state variable, but it sees an old value.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cause&lt;/strong&gt;: The closure was created when the effect ran, capturing the state at that moment.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fix&lt;/strong&gt;: Use &lt;code&gt;useRef&lt;/code&gt; to store a mutable value that can be read at any time without re-triggering the effect. Or, refactor to include the state in the dependency array and properly clean up the effect.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Use the ESLint Rule (and When to Ignore It)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;react-hooks/exhaustive-deps&lt;/code&gt; ESLint rule is a lifesaver. It statically analyzes your &lt;code&gt;useEffect&lt;/code&gt; calls and warns you about missing dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;99% of the time, you should follow its advice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When is it okay to ignore it? Very rarely. One legitimate case is when you &lt;em&gt;intentionally&lt;/em&gt; want to capture the initial value of a prop and never react to its changes. Even then, it's often cleaner to store that value in a &lt;code&gt;useRef&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// To ignore, add this comment. But think twice!&lt;/span&gt;
&lt;span class="c1"&gt;// eslint-disable-next-line react-hooks/exhaustive-deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tracing with Logs and Custom Hooks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Simple Logging&lt;/strong&gt;: The easiest way to see when an effect runs and cleans up.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Effect ran with value:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cleanup for value:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;myValue&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom &lt;code&gt;useTraceUpdate&lt;/code&gt; Hook&lt;/strong&gt;: Create a custom hook to see exactly which prop caused an effect to re-run.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTraceUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;changedProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;changedProps&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Changed props:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;changedProps&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  React DevTools Profiler
&lt;/h3&gt;

&lt;p&gt;The React DevTools are indispensable. Use the Profiler to record a user interaction and see exactly why your components re-rendered. The "Why did this render?" checkbox in the component inspector is a great starting point. For effects, the Profiler's flamegraph can help you spot long-running effects that might be slowing down your app.&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%2Fk6kg3wjbjn8diklxmun7.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%2Fk6kg3wjbjn8diklxmun7.gif" alt=" " width="720" height="279"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image Ref: &lt;a href="https://legacy.reactjs.org" rel="noopener noreferrer"&gt;https://legacy.reactjs.org&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Tips: &lt;code&gt;useRef&lt;/code&gt; for Tracking
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to access the previous value of a prop or state inside an effect. &lt;code&gt;useRef&lt;/code&gt; is perfect for this. Since updating a ref doesn't trigger a re-render, you can use it to store values across renders without affecting the component's lifecycle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevCountRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;prevCountRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Store the current count for the next render&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// No dependency array, so this runs on every render&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prevCountRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;prevCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. When Not to Use &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The most powerful lesson is often learning what a tool is &lt;em&gt;not&lt;/em&gt; for. Overusing &lt;code&gt;useEffect&lt;/code&gt; can lead to complex, inefficient, and buggy components. The golden rule is: &lt;strong&gt;if it can be done during render, don’t put it in &lt;code&gt;useEffect&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern: Unnecessary State Mirroring
&lt;/h3&gt;

&lt;p&gt;A common mistake is to use &lt;code&gt;useEffect&lt;/code&gt; to update a state variable in response to a prop change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Anti-pattern&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Mirrors the prop in state&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is redundant. You already have &lt;code&gt;user.name&lt;/code&gt; from props. The effect adds an unnecessary re-render and makes the data flow confusing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Derive state directly from props&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// No need for an effect or separate state&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Anti-Pattern: Computations and Derived State
&lt;/h3&gt;

&lt;p&gt;Don't use effects for calculations that can be done directly during rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Anti-pattern&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShoppingCart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTotal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newTotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTotal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newTotal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is overly complex. The total can be calculated on every render. If the calculation is expensive, use &lt;code&gt;useMemo&lt;/code&gt; to memoize it, but still don't use &lt;code&gt;useEffect&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Calculate during render&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShoppingCart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Correct (for expensive calculations)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShoppingCart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prefer Event Handlers for User Actions
&lt;/h3&gt;

&lt;p&gt;Side effects should be caused by a render, not a user event. If a user action (like clicking a button) needs to trigger a state change, do it directly in the event handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Anti-pattern&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;submittedValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSubmittedValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;submittedValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// send to API&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;submittedValue&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSubmittedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Submit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is indirect. The state change is just a trigger for the effect. The logic belongs in the event handler itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// send to API directly&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Submit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By avoiding these anti-patterns, you keep your components simpler, more predictable, and more performant.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Practical Examples &amp;amp; Patterns
&lt;/h2&gt;

&lt;p&gt;Theory is great, but code is better. Let's look at some common, production-ready patterns for &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern: Data Fetching with &lt;code&gt;AbortController&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the canonical example of a robust data fetching effect. It handles loading and error states, and it cancels the request if the component unmounts or the &lt;code&gt;userId&lt;/code&gt; changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.example.com/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Cleanup function to abort the request&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern: Syncing the Browser Tab Title
&lt;/h3&gt;

&lt;p&gt;A simple but effective use case. This effect synchronizes an external part of the browser (the tab title) with the component's state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useDocumentTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Store the original title so we can restore it on unmount&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;originalTitle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage in a component&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useDocumentTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Awesome Page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern: Custom Hooks Abstraction (e.g., &lt;code&gt;useLocalStorage&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;If you find yourself writing the same &lt;code&gt;useEffect&lt;/code&gt; logic repeatedly, it's time to extract it into a custom hook. This is one of the most powerful features of Hooks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;storedValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStoredValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storedValue&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;storedValue&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;storedValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStoredValue&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage in a component&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Light&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/option&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Dark&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/option&amp;gt;    &amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Wrap-Up
&lt;/h2&gt;

&lt;p&gt;Mastering &lt;code&gt;useEffect&lt;/code&gt; is a journey from understanding its rules to developing an intuition for its purpose. It’s not just a replacement for lifecycle methods; it’s a fundamentally different way of thinking about synchronizing your component with the world outside React.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;useEffect&lt;/code&gt; Cheat Sheet
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Use it for&lt;/strong&gt;: Side effects (data fetching, subscriptions, manual DOM changes).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;How to control it&lt;/strong&gt;: The dependency array is key.

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;[]&lt;/code&gt;: Runs once on mount.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;[dep]&lt;/code&gt;: Runs when &lt;code&gt;dep&lt;/code&gt; changes.&lt;/li&gt;
&lt;li&gt;  No array: Runs on every render (use with caution!).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;How to clean up&lt;/strong&gt;: Return a function from the effect. It runs before the next effect or on unmount.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;When to avoid it&lt;/strong&gt;: For derived state or simple computations. If you can calculate it during render, do it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Visual Summary
&lt;/h3&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%2F3mtksk5dx7xtukrww9ia.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%2F3mtksk5dx7xtukrww9ia.png" alt=" " width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Future of Effects
&lt;/h3&gt;

&lt;p&gt;The React team is always exploring ways to make effects even better. While nothing is set in stone, future versions of React might introduce new APIs or refine the behavior of &lt;code&gt;useEffect&lt;/code&gt; to make it even more intuitive and less error-prone. Staying engaged with the React community will keep you prepared for what's next.&lt;/p&gt;

&lt;p&gt;By following these principles, you can write cleaner, more efficient, and more predictable React components. Happy coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me on Medium, Dev.to, and LinkedIn! 🚀😊
&lt;/h2&gt;

&lt;p&gt;Your support and engagement mean the world to me.&lt;br&gt;&lt;br&gt;
Let's create a community of knowledge enthusiasts and professionals striving for excellence and continuous learning.  &lt;/p&gt;

&lt;p&gt;Click the links below to follow me on all platforms:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/mrajaeim" rel="noopener noreferrer"&gt;Connect on LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
📝 &lt;strong&gt;&lt;a href="https://medium.com/@mrajaeim" rel="noopener noreferrer"&gt;Follow on Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
💻 &lt;strong&gt;&lt;a href="https://dev.to/mrajaeim"&gt;Follow on Dev.to&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;




&lt;p&gt;I’m committed to providing the most up-to-date and relevant information.&lt;br&gt;&lt;br&gt;
As things evolve or new insights emerge, I may revisit and update this article to ensure it remains a valuable resource.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
