async/await is syntactic sugar over Promises, but understanding what’s actually happening underneath prevents a category of subtle async bugs.
// An async function ALWAYS returns a Promise, even if you return a plain value
async function getValue() { return 42; }
getValue().then(v => console.log(v)); // 42, wrapped in a Promise automatically
// Sequential vs parallel await - a very common performance mistake
async function sequentialSlow() {
const a = await fetchA(); // waits for A to finish...
const b = await fetchB(); // ...THEN starts B - unnecessarily serial
return [a, b];
}
async function parallelFast() {
const [a, b] = await Promise.all([fetchA(), fetchB()]); // both start immediately
return [a, b];
}
Error Handling Across Multiple Awaits
async function process() {
try {
const data = await fetchData();
const parsed = await parseData(data);
return parsed;
} catch (err) {
// catches a rejection from EITHER await above
console.error('Processing failed:', err);
throw err;
}
}
The sequential-vs-parallel mistake above is genuinely common and easy to miss in code review — two independent await calls that don’t depend on each other should almost always be wrapped in Promise.all rather than awaited one after another.