How JavaScript Promises Work Under the Hood
Microtasks, event loop phases, and internal states explained with clear step-by-step visual mental models.
Understanding the JavaScript Event Loop & Microtask Queue
Promises are one of the most fundamental concepts in modern asynchronous JavaScript. But what really happens under the hood when a Promise settles?
When you call new Promise(executor), JavaScript creates an object with internal slots [[PromiseState]] and [[PromiseResult]]. The state begins as pending, and transitions irreversibly to either fulfilled or rejected.
Microtasks vs Macrotasks
Promise reactions (.then(), .catch(), .finally()) are queued into the Microtask Queue, which takes priority over the standard Macrotask queue (such as setTimeout or DOM events) at the end of each tick.
// Example of microtask ordering
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
// Output: 1, 4, 3, 2
The Three Internal States
Every Promise starts as pending. It can then settle exactly once: either fulfilled with a result or rejected with a reason.
Think of a Promise as a receipt for a result that the engine will hand you later.
Creating and Consuming a Promise
The executor runs synchronously and immediately, while the callbacks passed to .then() and .catch() run asynchronously after the Promise settles via the microtask queue.
const profile = fetch("/api/profile")
.then((response) => response.json())
.then((user) => renderProfile(user))
.catch((error) => showError(error));
Why Chaining Works
Each call to .then() returns a completely new Promise. Returning a value fulfills the next step; throwing an error sends control to the nearest .catch() handler. This keeps each async step decoupled without nesting callbacks.
Practical Production Tip
Always handle failure at the boundary of an async workflow. A visible, graceful error state is far better than an uncaught silent promise rejection.
Reinforce these concepts
Practice with flashcards, test code in Web IDE, or take 60s speed drills on CodeShot.