Async/Await and the Event Loop in JavaScript
async/await is syntactic sugar over promises. Here is how it interacts with the event loop.
Async/Await and the Event Loop in JavaScript
async/await is syntactic sugar over promises. Understanding how it interacts with the event loop explains timing and ordering.
What async/await Does
An async function always returns a promise. await pauses the function until a promise settles. The rest of the function after await runs as a microtask.
Example
async function foo() { console.log("1"); await Promise.resolve(); console.log("2"); } foo(); console.log("3"); `` **Output**: `1, 3, 2`. 1. `foo()` is called. `"1"` logs (sync, on the stack). 2. `await` pauses `foo`. The rest (`"2"`) is scheduled as a microtask. 3. `"3"` logs (sync, on the stack). 4. Stack is empty. Microtasks run: `"2"` logs. ### `await` Yields to the Event Loop When `await` is hit, the function returns a promise and control goes back to the caller. The caller continues running synchronous code. Only when the stack is empty does the rest of the async function run (as a microtask). ### Multiple `await`s ```js async function foo() { console.log("a"); await fetch("/api"); console.log("b"); await fetch("/api2"); console.log("c"); } `` Each `await` pauses the function. The rest runs as a microtask when the awaited promise settles. Between `await`s, other code can run. ### Error Handling ```js async function foo() { try { const data = await fetch("/api"); return data.json(); } catch (err) { console.error(err); } } `` `try/catch` around `await` catches promise rejections. This is cleaner than `.catch()`. ### Parallel `await` ```js // sequential (slow) const a = await fetchA(); const b = await fetchB(); // parallel (fast) const [a, b] = await Promise.all([fetchA(), fetchB()]); `` Start all promises at once, then `await` them together. This is much faster for independent operations. ### `await` in Loops ```js // sequential (slow) for (const url of urls) { const data = await fetch(url); process(data); } // parallel (fast) const results = await Promise.all(urls.map(url => fetch(url))); results.forEach(process); `` Sequential `await` in a loop is slow. Use `Promise.all` for parallel. ### The Takeaway `async/await` is built on promises. `await` pauses the function and schedules the rest as a microtask. Control returns to the caller. The rest runs when the stack is empty. Use `try/catch` for errors. Use `Promise.all` for parallel operations. Avoid sequential `await` in loops for independent operations.
await pauses the async function and schedules the rest as a microtask. Control returns to the caller, who continues running synchronous code. When the stack is empty, the rest of the async function runs as a microtask.
Yes. async functions always return a promise. await pauses until a promise settles. The rest of the function after await runs as a microtask. async/await is syntactic sugar over promises.
Use try/catch around the await call. If the awaited promise rejects, the catch block runs. This is cleaner than .catch() with promise chains.
Start all promises at once and await them together with Promise.all: const [a, b] = await Promise.all([fetchA(), fetchB()]). This is much faster than sequential await for independent operations.
Because each await waits for the previous operation to finish before starting the next. For independent operations, this is unnecessary. Use Promise.all to start all operations at once and await them together.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

