advanced · 23 minute study
A promise is an outcome, not a background thread
Correctly composing async work avoids accidental serial delays, unhandled failures and duplicated side effects.
Useful preparation · 1 prerequisite
Use this as a map, not a lock. If these ideas are familiar, continue.
- The stack must empty before queued work runs — Promise/timer ordering explains why async UI updates and tests sometimes behave differently from the source's visual order.
First, build a mental model
A promise represents an eventual result. The operation may already have started before you await it. await pauses this async function's continuation, not the entire browser.
- Calling an async function starts its synchronous portion immediately.
- Awaiting a promise schedules the continuation after settlement.
- Promise.all composes independent promises; rejection does not automatically cancel siblings.
- Fetch rejects on network failures; HTTP error statuses must be inspected separately.
async function load(name, delay) {
console.log('start', name);
await new Promise(resolve => setTimeout(resolve, delay));
return name;
}
const a = load('A', 20);
const b = load('B', 5);
console.log(await Promise.all([a, b]));- Start
A and B both begin before the combined await.
- Settle
B may finish first, but Promise.all retains input order.
- Continue
The combined result is delivered once both fulfill.
Production thinking
Take this beyond the example.
Start independent reads together when appropriate, bound concurrency, and preserve explicit failure semantics. Do not infer cancellation, rollback or retry safety from Promise APIs.
Sources and further reading
Your evidence
unseen is a local learning signal, not a credential or proof of production competence.
Explain the mental model, then explicitly acknowledge it. Opening a page is not evidence.
Supported retries can complete this lesson. Independent evidence and delayed review determine the skill stage.
Next lesson · Only the current request may commit →