How the JS Engine + Web APIs Work
MedJavaScript runs in a runtime environment that includes the JS Engine (V8, SpiderMonkey, etc.) and Web APIs (provided by the browser or Node.js). The engine executes JavaScript code on the call stack, while Web APIs handle asynchronous operations like timers, DOM events, and network requests. Understanding how these components work together is key to understanding async JavaScript.
Interactive Visualization
Call Stack
<script>
Web APIs
fetch
setTimeout
URL
localStorage
sessionStorage
HTMLDivElement
document
indexedDB
XMLHttpRequest
Many more...
Event Loop
Task Queue
(empty)
Microtask Queue
(empty)
CodeSync
1console.log('1');23setTimeout(() => {4 console.log('timeout');5}, 0);67Promise.resolve()8 .then(() => console.log('promise'));910console.log('2');
Output
—
Script starts executing. Global EC pushed to call stack.
1 / 10
Key Insight: Microtasks (Promises) always run before macrotasks (setTimeout), even with 0ms delay!
Key Points
- JS Engine: Heap (memory) + Call Stack (execution)
- Web APIs: setTimeout, fetch, DOM, etc. (provided by environment)
- Engine executes code on call stack
- Async operations are handed off to Web APIs
- Web APIs queue callbacks when operations complete
- Event loop coordinates between stack and queues
Code Examples
The Runtime Components
console.log("Start"); setTimeout(() => { console.log("Timeout callback"); }, 1000); console.log("End"); // What happens: // 1. "Start" logs (sync, on call stack) // 2. setTimeout handed to Web API // - Browser starts 1s timer // - JavaScript continues immediately! // 3. "End" logs (sync) // 4. Call stack empty // 5. 1 second passes... // 6. Web API puts callback in queue // 7. Event loop moves callback to stack // 8. "Timeout callback" logs // Output: Start, End, (1s delay), Timeout callback
Async operations are handed to Web APIs. JavaScript continues executing without waiting.
setTimeout is Not Guaranteed Time
setTimeout(() => { console.log("Timer done"); }, 100); // Block the main thread for 200ms const start = Date.now(); while (Date.now() - start < 200) { // Busy wait } console.log("Loop done"); // Output: Loop done, Timer done // (not the other way around!) // Why? The timer callback can only run // when the call stack is empty. // The busy loop blocks everything.
setTimeout minimum delay, not guaranteed. Callback runs only when call stack is clear.
Common Mistakes
- Thinking JavaScript is multi-threaded
- Expecting setTimeout to be precise timing
- Not understanding that Web APIs are external to JS engine
Interview Tips
- Draw the diagram: Stack, Web APIs, Queues, Event Loop
- Explain how async operations work without threads
- Know that setTimeout is "at least" the delay, not exactly