Promises and async/await use the same async model, but production pitfalls show up in accidental serialization, missing cancellation, and error paths that escape the right boundary.
Promises and async/await
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.
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. |
// Cancellation pattern with fetch
const controller = new AbortController();
const req = fetch('/search?q=react', { signal: controller.signal });
controller.abort(); // cancel stale request
req.catch(err => {
if (err.name === 'AbortError') return;
throw err;
});
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 the relevant interview-question hub first, then move into a concrete study plan before targeted company sets.