Promises in depth
Compose asynchronous work — chaining, parallelism, and error handling.
- Explain a promise's three states
- Run asynchronous work in parallel with Promise.all
- Handle async errors with try/catch around await
The async lesson introduced promises and async/await. This one goes deeper:
the states a promise moves through, how to run async work in parallel, and how
errors propagate. These are the tools for real asynchronous code.
Three states
A promise is always in one of three states:
- pending — the work isn't finished yet.
- fulfilled — it completed with a value.
- rejected — it failed with an error.
It settles once (to fulfilled or rejected) and stays there. await gives you the
fulfilled value, or throws the rejection.
Sequential vs parallel
Awaiting one thing after another is sequential — fine when each step depends on the last, wasteful when they're independent:
// Sequential: ~2x as slow if the calls don't depend on each other
const a = await getUser(1);
const b = await getUser(2);Promise.all starts them together and waits for all to finish:
// Parallel: both run at once
const [a, b] = await Promise.all([getUser(1), getUser(2)]);This is the concurrency fundamentals lesson in practice: independent work should
overlap. Related helpers: Promise.allSettled (wait for all, successes and
failures) and Promise.race (settle as soon as the first one does).
Handling errors
A rejected promise that you await throws — so you catch it with ordinary
try/catch:
async function load() {
try {
const [a, b] = await Promise.all([getUser(1), getUser(2)]);
return { a, b };
} catch (err) {
console.error("one of the requests failed:", err);
return null;
}
}Note that with Promise.all, if any promise rejects, the whole thing rejects —
so a single try/catch covers them all.
An unhandled promise rejection won't crash the line that created it — it surfaces
later as an "unhandled rejection." Always await inside a try/catch, or attach
a .catch(...), so failures are handled where you expect.
Where to go next
Next: classes and prototypes — JavaScript's model for objects with shared behaviour.