HT
How Things Work

Web APIs & Browser Runtime

The browser environment that powers JavaScript β€” from DOM manipulation and fetch to Web Workers and requestAnimationFrame.

How It Works

JavaScript the language is surprisingly small. Most of what developers think of as 'JavaScript' β€” DOM manipulation, HTTP requests, timers, storage β€” are actually Web APIs provided by the browser. Understanding this boundary explains why the same JS code behaves differently in Node.js vs browsers.

1
JavaScript β‰  Browser APIs

JavaScript (the language) is just variables, functions, objects, and control flow. DOM manipulation, HTTP requests, timers, storage β€” these are all WEB APIs provided by the browser environment. They're NOT part of the ECMAScript specification.

2
Multi-Threaded Under the Hood

While JS is single-threaded, the browser uses multiple threads: a network thread for fetch, a timer thread for setTimeout, a rendering thread for layout/paint, and worker threads for Web Workers. The Event Loop bridges these threads back to JS.

3
requestAnimationFrame (rAF)

Unlike setTimeout, rAF is synced with the browser's display refresh rate (usually 60Hz). Callbacks run BEFORE the next paint, making it ideal for animations. The browser can also pause rAF in background tabs to save resources.

4
Web Workers: True Parallelism

Web Workers run JavaScript on a separate thread. They can't access the DOM but can do heavy computation without blocking the main thread. Communication is via postMessage (data is copied, not shared β€” unless using SharedArrayBuffer).

Key Concepts

🧡Main Thread

Runs JS, handles DOM updates, processes events, and executes rendering. Everything shares this thread, which is why long JS blocks UI.

🎞️requestAnimationFrame

Schedules a callback before the next paint. Runs at display refresh rate (~60fps). Automatically paused in background tabs.

βš™οΈWeb Workers

Run JS in a background thread. No DOM access, communicate via messages. Ideal for heavy computation (image processing, data parsing).

πŸ“‘Service Workers

Special workers that act as network proxies. Enable offline support, push notifications, and background sync. Part of Progressive Web App (PWA) patterns.

Common Web APIs
tsx
1// Web APIs are NOT JavaScript β€” they're browser-provided:
2
3// DOM API β€” manipulate the document
4document.querySelector("#app").innerHTML = "Hello";
5
6// Fetch API β€” HTTP requests (runs on network thread)
7const resp = await fetch("/api/data");
8const data = await resp.json();
9
10// setTimeout β€” delegates to the browser timer thread
11setTimeout(() => console.log("delayed"), 1000);
12
13// Web Worker β€” true multi-threading
14const worker = new Worker("heavy-task.js");
15worker.postMessage({ data: largeArray });
16worker.onmessage = (e) => console.log(e.data);
17
18// requestAnimationFrame β€” synced with display refresh
19function animate() {
20 updateCanvas();
21 requestAnimationFrame(animate); // ~16ms (60fps)
22}
23
24// IntersectionObserver β€” efficient scroll detection
25const observer = new IntersectionObserver((entries) => {
26 entries.forEach(e => {
27 if (e.isIntersecting) loadImage(e.target);
28 });
29});
πŸ’‘
Why This Matters

Knowing which APIs are browser-provided (not JavaScript) helps you: write isomorphic code, understand threading boundaries, optimize animations with rAF, offload work to Web Workers, and build offline-capable PWAs.

Common Pitfalls

⚠DOM APIs are synchronous and block the main thread. Batch DOM reads and writes separately to avoid layout thrashing.
⚠Web Workers can't access the DOM. If you need to update the UI based on worker results, you must postMessage back to the main thread.
⚠localStorage is synchronous and blocks the main thread. For large data, use IndexedDB (async) instead.
⚠fetch() doesn't reject on HTTP errors (404, 500). It only rejects on network failures. Always check response.ok.
Real-World Use Cases

1Smooth Animations with rAF

Scenario

Your JavaScript animation uses setInterval(update, 16) to target 60fps. It works on your monitor but stutters on 120Hz displays and wastes CPU in background tabs.

Problem

setInterval isn't synced with the display refresh rate. On 120Hz displays, you only update every other frame (visual stuttering). In background tabs, the interval keeps firing (wasted CPU and battery).

Solution

Replace setInterval with requestAnimationFrame. rAF automatically matches the display's refresh rate (60Hz, 120Hz, 144Hz) and pauses when the tab is hidden. Use the timestamp parameter for frame-rate-independent animation.

πŸ’‘

Takeaway: requestAnimationFrame is the only correct way to do visual animations in JavaScript. It's display-synced, power-efficient, and provides a high-resolution timestamp for smooth, frame-independent motion.

2Offloading Heavy Computation to Web Workers

Scenario

Your app parses a 50MB CSV file client-side. The UI freezes for 8 seconds during parsing β€” no spinner, no progress feedback. Users think the app crashed.

Problem

CSV parsing runs on the main thread, blocking all UI updates, event processing, and rendering. The browser can't even show a loading spinner because the rendering pipeline is blocked.

Solution

Move parsing to a Web Worker: const worker = new Worker('csv-parser.js'). Send the file via postMessage, receive parsed results async. The main thread stays responsive for UI updates and progress indication.

πŸ’‘

Takeaway: Any computation taking >50ms should be considered for a Web Worker. The 50ms threshold comes from the recommended budget for maintaining 60fps (16ms per frame, with time needed for rendering and event processing).