Async / Await
TL;DR
Introduced in ES8 (2017), async/await is syntactic sugar built directly on top of Promises. It allows you to write asynchronous, non-blocking code that reads top-to-bottom like standard synchronous code, completely eliminating .then() chains.
Mental Model
How It Works
async: When placed before a function, it guarantees that the function will always return a Promise. Even if youreturn 5, JavaScript secretly wraps it inPromise.resolve(5).await: Can only be used inside anasyncfunction. When the engine hits anawaitkeyword, it evaluates the Promise to its right. It then pauses the execution of that specific function until the Promise settles. While the function is paused, the Call Stack is free to do other work.
Error Handling:
Instead of appending .catch(), you wrap await statements in standard synchronous try/catch blocks.
Example
// A mock network request
function getCoffee() {
return new Promise(resolve => setTimeout(() => resolve("☕"), 1000));
}
// --- The Old Way ---
function makeBreakfastThen() {
getCoffee()
.then(coffee => {
console.log(`Got ${coffee}`);
})
.catch(err => console.error(err));
}
// --- The Modern Way ---
async function makeBreakfastAsync() {
try {
// Execution pauses here for 1 second!
const coffee = await getCoffee();
// This line won't run until the promise above resolves.
console.log(`Got ${coffee}`);
} catch (err) {
console.error("Failed to get coffee", err);
}
}
Common Output Question
async function test() {
return 1;
}
const result = test();
console.log(result === 1);
Q: What does this output and why?
A: false.
An async function ALWAYS returns a Promise. The result variable does not hold the number 1. It holds a pending Promise object. console.log(Promise === 1) is false. To get the 1, you must do result.then(val => console.log(val)) or await test().
Senior Interview Question
Q: Look at the following code. How long does it take to execute, and how would you optimize it?
async function fetchDashboard() {
const users = await fetch('/api/users');
const posts = await fetch('/api/posts');
const stats = await fetch('/api/stats');
return { users, posts, stats };
}
A: Assuming each fetch takes 1 second, this code takes 3 seconds to execute. Because of await, the second fetch cannot start until the first one is completely finished. This is a massive performance bottleneck known as “Sequential Awaiting”.
Since the three requests do not depend on each other, they should be fired concurrently using Promise.all().
Optimized (takes 1 second):
async function fetchDashboard() {
const [users, posts, stats] = await Promise.all([
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/stats')
]);
return { users, posts, stats };
}