Promises are the foundation of all modern JavaScript async code — and most developers only use 10% of the API. Creating promises, chaining correctly, handling errors without swallowing them, and knowing when to use Promise.all vs allSettled vs race vs any — these distinctions determine correctness and performance in production code.
⚡ TL;DR: Promises have three states: pending, fulfilled, rejected. Chain with .then() for success, .catch() for errors. Promise.all fails fast. Promise.allSettled waits for all. Promise.race returns first settled. Promise.any returns first fulfilled. async/await is syntactic sugar over promises.
Creating promises from scratch
// Promise constructor: takes executor (resolve, reject)
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const fetchWithTimeout = (url, timeoutMs) => new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('Timeout')), timeoutMs);
fetch(url)
.then(res => { clearTimeout(timer); resolve(res); })
.catch(err => { clearTimeout(timer); reject(err); });
});
// Promisify callback-style functions
const { promisify } = require('util');
const readFile = promisify(require('fs').readFile);
await readFile('file.txt', 'utf8');
Chaining — return value propagation
// Every .then() returns a new Promise
// Return value becomes next .then()'s input
fetch('/api/user')
.then(res => res.json()) // Returns Promise
.then(raw => normalize(raw)) // Returns UserNormalized
.then(user => saveToCache(user)) // Returns Promise
.catch(err => handleError(err)); // Catches ANY error above
// Mistake: forgetting to return inside .then()
fetch('/api/user')
.then(res => {
res.json(); // NO return! Next .then() gets undefined
})
.then(data => console.log(data)); // undefined
// Correct:
.then(res => res.json()) // Implicit return with arrow fn
Promise combinators — all four
const p1 = fetch('/api/users');
const p2 = fetch('/api/posts');
const p3 = fetch('/api/settings');
// Promise.all: all succeed or fail together
const [users, posts, settings] = await Promise.all([p1, p2, p3]);
// If p2 rejects: immediately rejects, p1 and p3 results lost
// Promise.allSettled: wait for all, get individual results
const results = await Promise.allSettled([p1, p2, p3]);
results.forEach(r => {
if (r.status === 'fulfilled') use(r.value);
if (r.status === 'rejected') log(r.reason);
});
// Use when: partial success acceptable (dashboard widgets)
// Promise.race: first to settle wins
const result = await Promise.race([fetch(url), delay(5000).then(() => { throw new Error('timeout'); })]);
// Promise.any: first to FULFILL (ignores rejections)
const fastest = await Promise.any([serverA(), serverB(), serverC()]);
Error handling — the right way
// WRONG: unhandled rejection
async function bad() {
const data = await riskyCall(); // Throws? Unhandled rejection!
}
// WRONG: catch that swallows
async function alsoBad() {
try {
return await riskyCall();
} catch (e) {} // Error silently swallowed!
}
// RIGHT: handle or re-throw
async function good() {
try {
return await riskyCall();
} catch (e) {
logger.error('riskyCall failed', e);
throw e; // Re-throw unless you can meaningfully recover
}
}
// Result pattern — explicit error as value
async function safe() {
try { return { ok: true, data: await riskyCall() }; }
catch (e) { return { ok: false, error: e.message }; }
}
- ✅ Always return inside .then() callbacks
- ✅ Promise.allSettled when partial success is acceptable
- ✅ Promise.race for timeouts and hedged requests
- ✅ Promise.any for redundant sources — fastest wins
- ❌ Never swallow errors in .catch() without at minimum logging
- ❌ Never mix .then()/.catch() chains with async/await in the same function
Promises are the foundation of the async/await guide — async/await is syntax over promises. External reference: MDN Promise documentation.
Recommended Reading
→ Designing Data-Intensive Applications — The essential book every senior developer needs.
→ The Pragmatic Programmer — Timeless engineering wisdom for writing better code.
Affiliate links. We earn a small commission at no extra cost to you.
Free Weekly Newsletter
🚀 Don’t Miss the Next Cheat Code
Join 1,000+ senior developers getting expert JS, Python, AWS and system design secrets weekly.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
