async/await explained: Promises + Event Loop

Most developers use async/await. Fewer understand what’s actually happening under the hood. async/await didn’t change how JavaScript handles asynchronous code. It just made it easier to read. Under the hood: - Every async function returns a Promise - Every await pauses execution of that function - Control goes back to the call stack — nothing is blocked No magic. Just Promises + the Event Loop. Here’s what actually happens: async function getData() { const data = await fetchSomething(); console.log(data); } → getData() is called An execution context is pushed onto the call stack → await is hit 🟡 fetchSomething() runs Execution of getData() pauses (non-blocking) → Call stack is free JavaScript continues handling other work → Promise resolves ✅ Its continuation is pushed to the Microtask Queue → Event Loop checks 🔄 Call stack empty → process Microtasks first → Execution resumes 🟢 getData() continues from where it paused console.log(data) runs → Function completes Call stack is clear again This is why microtasks run before setTimeout. After the call stack is empty, the Event Loop fully drains the Microtask Queue before touching the Callback Queue. Even a 0ms setTimeout waits. console.log("start"); setTimeout(() => console.log("timeout"), 0); Promise.resolve().then(() => console.log("promise")); console.log("end"); Output: start end promise timeout async/await is just syntactic sugar over Promises. The runtime behaviour is exactly the same. Once this clicks, async bugs stop feeling random — and start feeling predictable. What part of async behavior still trips you up? #JavaScript #WebDevelopment #Frontend #AsyncAwait

To view or add a comment, sign in

Explore content categories