JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
93: Web Workers for Background Processing
Imagine you're running a small cafe. You're the only employee. You take the orders, you pour the coffee, and you also bake the elaborate, five-layer cakes. For a while, it works. But then, a customer orders a cake that takes three hours to bake. Because you're the only one there, you have to stay in the kitchen for those three hours. While you're baking, the front door is locked, the phone is ringing unanswered, and the other customers are staring at you through the window, wondering why the shop has effectively ceased to exist.
In this scenario, you are the JavaScript main thread. The cafe is your browser tab. When you run a massive calculation—like processing a 50MB CSV file or calculating prime numbers—you're "baking the cake." Because JavaScript is single-threaded, the UI freezes. The buttons don't click, the animations stop, and the user thinks your app has crashed.
Web Workers are how we hire a chef. You stay at the front counter handling the customers (the UI), and you send a ticket to the chef in the back (the Worker). The chef does the heavy lifting in a separate thread, and when the cake is done, they ring a bell to let you know it's ready to be served.
The Cost of Being Single-Threaded
I've seen plenty of juniors try to solve UI freezing by using setTimeout or async/await. Here is the hard truth: async/await doesn't actually run code in parallel. It just manages when things happen. If you have a loop that runs a billion times, it doesn't matter if it's inside an async function; it will still block the main thread and freeze your page. That's where Web Workers come in. They provide a truly separate execution context.
Offloading the Heavy Lifting
To use a Worker, you need a separate file. You can't just define the worker function inside your main script because the browser needs to spawn a completely new OS-level thread for it. Let's say we want to find the sum of a massive array of numbers without locking up our "Submit" button.
First, we create our worker file, calculator.js:
// calculator.js
self.onmessage = function(e) {
const data = e.data; // This is the array we sent from the main thread
console.log('Worker: Starting heavy calculation...');
// Simulate a heavy task
const result = data.reduce((acc, num) => acc + num, 0);
// Send the result back to the main thread
self.postMessage(result);
};
Now, in your main JavaScript file, you instantiate the worker and set up the communication channel:
// main.js
const myWorker = new Worker('calculator.js');
const bigData = Array.from({ length: 10000000 }, () => Math.floor(Math.random() * 100));
// Send the data to the worker
myWorker.postMessage(bigData);
// Listen for the result
myWorker.onmessage = function(e) {
console.log('Main Thread: The worker finished! Result is: ' + e.data);
};
console.log('Main Thread: I am still responsive! I can handle clicks and scrolls.');
The postMessage Handshake
Notice that the main thread and the worker don't share memory. You can't just reach into the worker and change a variable, and the worker can't touch the DOM. This is a safety feature—if they both tried to change the same piece of data at once, you'd end up with "race conditions," which are a nightmare to debug.
Instead, they communicate via postMessage(). Think of it like sending a letter. You pack your data into an envelope, send it off, and wait for a reply. When you call postMessage, the browser actually clones the data you're sending. For most objects, this is fine, but if you're moving massive amounts of data (like raw image pixels), you'll eventually want to look into "Transferable Objects," which move the data instead of copying it. But for 95% of use cases, the standard cloning is exactly what you need.
One last tip: remember to terminate your workers when you're done with them using myWorker.terminate(). If you keep spawning workers without killing them, you'll leak memory and eventually slow the user's entire computer to a crawl.
📋 Practical Task
Build a Non-Blocking Prime Number Finder
Your goal is to create a page that calculates whether a very large number is prime without freezing the browser's UI.
- The Interface: Create an HTML page with an input field for a number, a "Check Prime" button, and a loading spinner (a simple CSS animation or just a text element saying "Calculating...").
- The Worker: Create a
primeWorker.jsfile. It should receive a number and run a loop to check for primality. To make the "blocking" effect obvious, use a very large prime or a very large odd number. - The Integration:
- When the button is clicked, the main thread should show the loading spinner and
postMessagethe number to the worker. - The main thread must remain responsive (try adding a counter button on the page that increments a number; it should keep working while the prime is being calculated).
- When the worker returns the result, hide the spinner and display whether the number was prime.
- When the button is clicked, the main thread should show the loading spinner and
There are no comments for now.