Promises and async/await use the same async model, but production decisions are really about concurrency, stale-request cancellation, request identity, and error boundaries rather than syntax alone.
Use this JavaScript interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
Promises and async/awaitFrontend interview answer
This JavaScript interview question tests whether you can explain Promises vs async await: concurrency, stale-request control, and production pitfalls, connect it to production trade-offs, and handle common follow-up questions.
- Promises vs async await: concurrency, stale-request control, and production pitfalls explanation without falling back to memorized docs wording
- Async Await and Concurrency reasoning, edge cases, and production failure modes
- How you would answer the most likely JavaScript interview follow-up
Short version
A Promise represents a future result. async/await is a cleaner way to consume Promises. Same engine behavior, different readability style, but the production pitfall is assuming await is always clearer when it may accidentally serialize independent work. A strong production answer usually shows both independent work started together and one stale-request guard, because syntax is not the hard part.
Question | Answer |
|---|---|
Do async functions return Promises? | Yes, always. |
Does await block the whole app? | No. It pauses only that async function. |
Does await change event-loop priority? | No. Promise continuation still resumes as microtasks. |
function fetchUser(id) {
return Promise.resolve({ id, name: 'Ada' });
}
// Promise style
fetchUser(1)
.then(user => user.name)
.then(name => console.log(name))
.catch(console.error);
// async/await style
async function run() {
try {
const user = await fetchUser(1);
console.log(user.name);
} catch (err) {
console.error(err);
}
}
run();
Most important practical rule: avoid accidental serialization
// ❌ Sequential (slow if independent)
const a = await fetch('/a').then(r => r.json());
const b = await fetch('/b').then(r => r.json());
// ✅ Parallel (faster)
const [a2, b2] = await Promise.all([
fetch('/a').then(r => r.json()),
fetch('/b').then(r => r.json())
]);
Need | Preferred API | Why |
|---|---|---|
All must succeed |
| Fast-fails on first rejection. |
Need every outcome |
| Get success+failure results together. |
First success wins |
| Useful for fallback mirrors/CDNs. |
First settled wins |
| Timeout or first-responder patterns. |
let activeController;
let latestRequestId = 0;
async function loadDashboard(userId) {
activeController?.abort();
const controller = new AbortController();
activeController = controller;
const requestId = ++latestRequestId;
try {
const [profile, notifications] = await Promise.all([
fetch(`/api/profile/${userId}`, { signal: controller.signal }).then(r => r.json()),
fetch(`/api/notifications/${userId}`, { signal: controller.signal }).then(r => r.json())
]);
if (requestId !== latestRequestId) return; // stale result guard
renderDashboard({ profile, notifications });
} catch (err) {
if (err.name === 'AbortError') return;
reportError(err);
}
}
Why this pattern wins in production
Start independent requests together, keep one try/catch boundary, and pair AbortController with a request-identity guard when older work must never overwrite newer UI state.
Practical scenario
Autocomplete requests fire on each keystroke. You debounce input, cancel stale requests, and only render the latest resolved result to avoid flicker and race bugs.
Common pitfalls
- Using
awaitinside loops when calls are independent. - Forgetting terminal error handling.
- Assuming Promise cancellation exists automatically.
Promise is the contract for future data. await is just cleaner punctuation when reading that contract.
- Promises and async/await are the same async model.
- Use try/catch (or .catch) consistently.
- Parallelize independent work with
Promise.all. - Use cancellation for stale UI requests.
Use this as one explanation rep, then continue with the JavaScript interview questions cluster or a guided prep path.