VisualJS

Runtime Internals

See what the JavaScript engine does behind the scenes — event loop, promises, async execution, and task scheduling.

Event Loop

See how JavaScript orchestrates sync code, microtasks, and macrotasks.

console.log("1: sync");

setTimeout(() => {
  console.log("4: macrotask");
}, 0);

Promise.resolve().then(() => {
  console.log("3: microtask");
});

console.log("2: sync");
Speed:1000ms
Tick #0
Call Stack
empty
Event Loop
idle
stack
micro
macro
Microtask Queue
empty
Macrotask Queue
empty

Promise State Machine

Pending → Fulfilled or Rejected. Irreversible once settled.

const p1 = new Promise((resolve) => {
  setTimeout(() => resolve("data"), 1000);
});

const p2 = p1.then((val) => val.toUpperCase());

const p3 = p2.catch((err) => "fallback");
pending
fulfilled
rejected
Click a demo button to see promises in action

Async Suspension

await pauses execution, yields control, then resumes when the value is ready.

async function fetchUser() {
  console.log("start");
  const response = await fetch("/api/user");
  console.log("got response");
  const data = await response.json();
  console.log("parsed:", data);
  return data;
}

fetchUser();
console.log("after call");
Async Function State
Run the demo to see async execution
Call Stack
empty

Task Scheduling

setTimeout, setInterval, and queueMicrotask — when do they actually run?

console.log("1");

setTimeout(() => console.log("2"), 1000);

setTimeout(() => console.log("3"), 0);

queueMicrotask(() => console.log("4"));

console.log("5");

// Output: 1, 5, 4, 3, 2
Registered Timers
No timers registered
Output
waiting...

Runtime Queue Inspector

Live view of all active, waiting, and prioritized tasks.

0
Stack Depth
0
Microtasks
0
Macrotasks
0
Event Loop Tick
Active Tasks
No active tasks
Waiting Tasks
No waiting tasks
Event Log
No events yet
Execution Priority
1
Synchronous code
Call stack executes first
2
Microtasks
Promise.then, queueMicrotask — drain fully before next macro
3
Macrotasks
setTimeout, setInterval — one per event loop tick
4
requestAnimationFrame
Before next repaint