Web APIs & Node APIs
The Runtime's Toolbox
LinkedIn Hook
Here's a trick question interviewers love: "Is
setTimeoutpart of JavaScript?"Most candidates say yes. They're wrong.
setTimeout,fetch,addEventListener,geolocation,requestAnimationFrame— NONE of these are JavaScript. Open the ECMAScript spec and you won't find any of them. They are Web APIs provided by the browser. In Node.js, the equivalents are provided by a C library called libuv.This distinction matters more than it sounds. It's the reason the same
setTimeout(fn, 0)code behaves differently in Chrome, Node, and a Web Worker. It's the reason your JS engine never blocks onfetch. And it's the reasondocumentis undefined in Node whilefsis undefined in the browser.In this lesson you'll see exactly which APIs the browser ships (timers, network, DOM, GPS, animation), which ones Node ships (libuv: fs, http, setImmediate, process.nextTick), and how both runtimes feed the same Event Loop you learned in Lesson 3.1.
Read the full lesson -> [link]
#JavaScript #WebAPIs #NodeJS #libuv #InterviewPrep #Frontend #Backend #AsyncJS
What You'll Learn
- Why
setTimeoutandfetchare NOT part of the JavaScript language - The common Web APIs the browser ships and which queue each one feeds
- How Node.js replaces Web APIs with libuv and its own async primitives
Web APIs Are Not Part of JavaScript
Web APIs are not part of JavaScript itself. They are provided by the browser (or by Node.js in the form of C++ APIs). They run operations in separate threads while your JS code continues executing.
Think of Web APIs as external contractors that your company (the JS engine) hires. You hand them a task ("call me back in 2 seconds" or "fetch data from this URL"), and they do the work outside your office. When they're done, they drop the result in your mailbox (the queue).
Common Web APIs
| Web API | What It Does | Queue It Uses |
|---|---|---|
setTimeout / setInterval | Timer-based callbacks | Callback Queue (Macrotask) |
fetch | HTTP requests | Microtask Queue (via Promises) |
| DOM Event Listeners | click, scroll, keydown, etc. | Callback Queue (Macrotask) |
geolocation | GPS/location access | Callback Queue |
requestAnimationFrame | Animation frame callbacks | Runs before next repaint (special) |
MutationObserver | DOM change observation | Microtask Queue |
XMLHttpRequest | Legacy HTTP requests | Callback Queue |
Code Example — Multiple Web APIs
console.log("1: Synchronous");
setTimeout(() => {
console.log("2: setTimeout (0ms)");
}, 0);
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(() => console.log("3: fetch resolved"));
document.addEventListener("click", () => {
console.log("4: click event");
});
console.log("5: Synchronous again");
Output (assuming no click happens):
1: Synchronous
5: Synchronous again
3: fetch resolved <- microtask (Promise) runs first
2: setTimeout (0ms) <- macrotask runs after microtasks
Step-by-step:
"1: Synchronous"-> call stack -> prints immediatelysetTimeout-> handed to Web API (timer thread) -> callback goes to Callback Queue when timer completesfetch-> handed to Web API (network thread) -> when response arrives,.thencallback goes to Microtask QueueaddEventListener-> registered with Web API -> callback only enters queue when a click actually happens"5: Synchronous again"-> call stack -> prints immediately- Call stack empty -> Event Loop checks Microtask Queue first -> fetch
.thenruns -> prints "3" - Microtask Queue empty -> Event Loop checks Callback Queue -> setTimeout callback runs -> prints "2"
The Web API "Parking Lot"
// These all go to Web APIs — they DON'T block the call stack
setTimeout(() => console.log("timer done"), 2000); // Timer thread
fetch("/api/data").then(res => console.log(res)); // Network thread
navigator.geolocation.getCurrentPosition(pos => {}); // Geolocation thread
console.log("I run immediately — none of the above blocks me!");
The call stack doesn't wait for any of these. It hands them off to the browser and moves on.
The Node.js Counterpart — libuv
Node.js has no browser, so it has no Web APIs. It uses libuv, a C library that provides both the event loop and a thread pool for async I/O. When you call fs.readFile, http.createServer, setImmediate, or process.nextTick, the V8 engine hands the work to libuv the same way a browser hands work to its Web APIs. Node-specific primitives include setImmediate (fires after the current I/O phase), process.nextTick (drained before microtasks), and the fs/net/http modules backed by libuv's thread pool. Same Event Loop concept, different runtime.
// Node.js — same async model, different APIs
const fs = require("fs");
console.log("1: start");
fs.readFile("./data.txt", "utf8", (err, data) => {
console.log("3: file read done");
});
setImmediate(() => {
console.log("4: setImmediate");
});
console.log("2: end");
The fs.readFile work is handed to libuv's thread pool; setImmediate is queued by libuv's event loop — neither blocks the call stack.
Common Mistakes
- Saying
setTimeoutis a JavaScript function. It's a Web API (browser) or libuv binding (Node) — the ECMAScript spec never mentions it. - Assuming Node.js has access to
document,window, orfetch-from-DOM. Node has its own async world backed by libuv; thefetchthat shipped with Node 18+ is a Node API, not a browser one. - Treating
requestAnimationFrameas a normal macrotask. It's a special Web API synchronized with the browser repaint cycle — not the same assetTimeout.
Interview Questions
Q: Are Web APIs part of JavaScript?
No. Web APIs (setTimeout, fetch, DOM APIs, geolocation, etc.) are provided by the browser runtime, not the JavaScript engine (V8, SpiderMonkey, etc.). In Node.js, equivalent functionality is provided by C++ APIs (like
libuvfor timers and I/O).
Q: What thread does setTimeout run on?
The timer for
setTimeoutruns on a separate browser thread (not the main JS thread). The JavaScript engine only registers the callback and moves on. When the timer completes, the browser places the callback in the Callback Queue. The Event Loop then moves it to the call stack when the stack is empty.
Q: What's the difference between requestAnimationFrame and setTimeout for animations?
requestAnimationFrameis synchronized with the browser's repaint cycle (~60fps), making animations smoother. It runs before the next repaint.setTimeoutruns as a macrotask with no synchronization to rendering, which can cause janky animations.requestAnimationFramealso pauses in background tabs, saving resources.
Q: What replaces Web APIs in Node.js?
libuv. It's a C library that provides Node's event loop and a thread pool for async I/O. Node-specific async primitives like
fs.readFile,http.createServer,setImmediate, andprocess.nextTickare implemented on top of libuv rather than browser Web APIs.
Quick Reference — Cheat Sheet
WEB APIs vs NODE APIs — QUICK MAP
Browser (Web APIs):
setTimeout / setInterval -> Callback Queue
fetch -> Microtask Queue (Promise)
addEventListener (DOM) -> Callback Queue
geolocation -> Callback Queue
requestAnimationFrame -> runs before next repaint
MutationObserver -> Microtask Queue
XMLHttpRequest -> Callback Queue
Node.js (libuv-backed):
fs.readFile / fs.writeFile -> thread pool -> Callback Queue
http.createServer -> libuv sockets -> Callback Queue
setImmediate -> check phase (after I/O)
process.nextTick -> drained BEFORE microtasks
Promises / queueMicrotask -> Microtask Queue
Rule:
JS engine never blocks on these.
Runtime does the work, queues the callback.
Previous: The Event Loop -> How One-Threaded JS Never Freezes Next: Callback Queue -> The Macrotask Line
This is Lesson 3.2 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.