The Secret Life of JavaScript: The Clone

Published: (February 21, 2026 at 02:57 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

How to use Web Workers to protect the Main Thread and prevent frozen UIs.

Timothy clicked the Export Report button. A loading spinner appeared, but it was frozen solid. The entire browser window became unresponsive. After ten seconds the UI unfroze and the file downloaded.

“It works,” Timothy said, “but the application completely dies while it’s processing the data.”

Margaret pulled up a chair. “You have built a beautiful kitchen, Timothy, but you only have one chef. If you ask him to chop ten thousand onions, he cannot also greet the customers.”

The Single Thread

Margaret opened the performance tab and pointed to a massive, solid yellow block taking up the timeline.

“JavaScript is single‑threaded,” she explained. “We call it the Main Thread, but you should think of it as the UI Thread. Its primary job is to paint the screen, run animations, and listen for clicks.”

Timothy pointed to his code. “But I used async and await! I thought that made it non‑blocking.”

async is for waiting,” Margaret corrected. “When you await a network request, the chef puts the soup on the stove and walks away to do other things. But data processing—like formatting a massive CSV or doing heavy math—is active work. The chef is chopping. He cannot step away.”

The Clone

“So how do I process the data without freezing the screen?” Timothy asked.

“You hire a sous‑chef,” Margaret said. “You create a Web Worker.”

Margaret added a new file worker.js:

// worker.js – The Sous‑Chef's Room
self.onmessage = function (event) {
  const rawData = event.data;

  // The chef is chopping the onions in the background
  const processedCSV = heavyDataProcessing(rawData);

  // Send the finished product back to the kitchen
  self.postMessage(processedCSV);
};

A Web Worker is a literal clone of the JavaScript engine, running in parallel with the original. It cannot access the DOM or UI elements, but it can use APIs like fetch() and setTimeout().

The Dispatch

Back in the main application file, Margaret wired up the export button:

// main.js – The Kitchen (UI Thread)
const exportButton = document.getElementById('export-btn');

exportButton.addEventListener('click', () => {
  // 1. Show the spinning UI
  showLoadingSpinner();

  // 2. Hire the sous‑chef
  const worker = new Worker('worker.js');

  // 3. Listen for the note back under the door
  worker.onmessage = function (event) {
    const processedCSV = event.data;
    downloadFile(processedCSV);
    hideLoadingSpinner();

    // Fire the sous‑chef so he doesn't consume memory
    worker.terminate();
  };

  // 4. Handle emergencies in the kitchen
  worker.onerror = function (error) {
    console.error('Sous‑chef had a breakdown:', error);
    hideLoadingSpinner();
    showErrorMessage();
    worker.terminate();
  };

  // 5. Slide the raw data under the door
  const rawData = getMassiveDataset();
  worker.postMessage(rawData);
});

Running the code again, Timothy saw the spinner spin smoothly, could interact with other UI elements, and received the file download after ten seconds without any freeze.

The Architectural Divide

“This changes everything,” Timothy remarked, watching the smooth animation.

“It forces you to think differently,” Margaret agreed. “Junior developers put everything on the Main Thread and hope the computers are fast enough to hide it. Senior developers protect the Main Thread at all costs, treating it purely as a presentation layer. If a task takes more than ~50 ms of pure CPU time, they hand it off to a Worker.”

Senior Tip: Transferable Objects

postMessage creates a copy of the data. For massive datasets, copying can be costly. Use Transferable Objects (e.g., ArrayBuffer) to transfer ownership of the memory to the worker without copying, achieving an instant handoff with zero overhead.

The Spinner

With the worker in place, the spinner spins freely while the main thread remains responsive—greeting customers, answering the phone, and keeping the place alive—while the sous‑chef quietly chops onions in the back.

0 views
Back to Blog

Related posts

Read more »

Undefined vs Not Defined

Undefined undefined is a special keyword in JavaScript. It means the variable exists in memory, but no value has been assigned yet. During the creation phase o...