Async patterns you will use at work
Real services fan work out: load ten feeds, call three APIs, and accept that some of them fail or hang. The tools from the last two lessons compose into a small set of patterns that cover most production async code — and most senior-sounding interview answers. This lesson works through three: partial failure, timeouts, and looping over async work without the classic footgun.
Pattern 1: partial failure. Promise.all is the wrong tool when one failure should not sink the whole batch — it rejects on the first error and discards everything else. Promise.allSettled waits for every input and reports each outcome as { status: "fulfilled", value } or { status: "rejected", reason }, so you can render nine widgets plus one error message instead of a blank page.
Code exercise · javascript
Run it. User 2 fails, but users 1 and 3 still arrive. allSettled itself never rejects — you inspect each result's status yourself.
Pattern 2: timeouts with race
Nothing in the language times a promise out for you — a network call that never settles would leave an await hanging forever. The standard fix is Promise.race([work, timeout]): race settles with whichever input settles first, so pairing the real work with a promise that rejects after a deadline turns a hung call into a catchable error.
Code exercise · javascript
Your turn. Implement `timeout(ms)`: a promise that REJECTS with `new Error("timed out")` after `ms` milliseconds. The fast task then wins its race, and the slow one loses to the 30 ms deadline.
Pattern 3: the forEach footgun
array.forEach(async (item) => ...) looks like it awaits each item. It does not: forEach ignores its callback's return values, so it fires every async callback and returns immediately — the awaits pause the callbacks, not your function. This bug ships to production constantly.
The working rules: when steps must run one at a time (rate limits, ordered writes), use for...of with await in the body. When the items are independent, build the promises with map and await Promise.all(...) (lesson 6-2).
Code exercise · javascript
Run it. The forEach version returns before a single user has loaded, and its callbacks run in parallel. The for...of version (started 100 ms later so the outputs don't interleave) genuinely waits for each item.
Quiz
Ten independent uploads, and you must report the outcome of every single one even if some fail. Which tool fits?