Promises and Async/Await in JavaScript — Complete Guide
The Interview Question
Explain how Promises work. How does async/await relate to Promises? How do you handle errors?
Expert Answer
A Promise represents a value that may not be available yet. It's in one of three states: pending, fulfilled, or rejected. Once settled (fulfilled or rejected), it never changes state again. You chain operations with .then() for success and .catch() for errors. Each .then() returns a new Promise, enabling chaining. Async/await is syntactic sugar over Promises — an async function always returns a Promise, and await pauses execution until the Promise settles. The key advantage of async/await is readability: sequential async operations read like synchronous code. For error handling, you have two approaches: .catch() in the Promise chain, or try/catch around await calls. In practice, async/await with try/catch is the modern standard. For parallel execution, use Promise.all (fails fast if any reject) or Promise.allSettled (waits for all, returns status of each).
Key Points to Hit in Your Answer
- Promises are immutable once settled — resolved stays resolved
- async functions always return a Promise
- await only works inside async functions (or top-level in modules)
- Promise.all fails fast on first rejection; Promise.allSettled waits for everything
- Unhandled promise rejections crash Node.js — always handle errors
- Common pitfall: await in a loop is sequential; Promise.all is parallel
Code Example
// Sequential vs Parallel — common interview question
// BAD: Sequential (slow — each waits for the previous)
async function getSequential(ids) {
const results = [];
for (const id of ids) {
results.push(await fetchUser(id)); // waits each time
}
return results;
}
// GOOD: Parallel (fast — all requests fire at once)
async function getParallel(ids) {
return Promise.all(ids.map(id => fetchUser(id)));
}
// Promise.allSettled — handle mixed results
const results = await Promise.allSettled([
fetchUser(1), // succeeds
fetchUser(999), // fails (404)
fetchUser(2), // succeeds
]);
// [{ status: 'fulfilled', value: ... },
// { status: 'rejected', reason: ... },
// { status: 'fulfilled', value: ... }]
What Interviewers Are Really Looking For
The sequential-vs-parallel await question is an interview classic. If you immediately identify that await in a loop is sequential and suggest Promise.all, that's a strong signal. Knowing when to use Promise.allSettled vs. Promise.all shows practical experience with real error scenarios.
Practice This Question with AI Grading
Reading about interview questions is a start — but practicing with real-time AI feedback is how you actually get better. Goliath Prep grades your answers instantly and tells you exactly what you're missing.
Start Practicing Free →