Promises
Handle asynchronous results with then, catch, and Promise combinators
Overview
A Promise represents a value that may be available now, later, or never. Promises have three states: pending, fulfilled, or rejected. They replace deeply nested callbacks with chainable .then() handlers.
Syntax / Usage
const fetchUser = (id) =>
new Promise((resolve, reject) => {
if (!id) reject(new Error('Missing id'))
else resolve({ id, name: 'Ada' })
})
fetchUser(1)
.then((user) => console.log(user.name))
.catch((err) => console.error(err))
.finally(() => console.log('done'))
// Creating resolved/rejected promises
Promise.resolve(42)
Promise.reject(new Error('fail'))
// Combinators
Promise.all([p1, p2]) // all succeed or first reject
Promise.allSettled([p1, p2]) // wait for all, never rejects
Promise.race([p1, p2]) // first settled wins
Examples
Fetch JSON from an API:
function getJson(url) {
return fetch(url).then((res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`)
return res.json()
})
}
getJson('/api/users/1')
.then((user) => renderProfile(user))
.catch(showError)
Retry with exponential backoff:
function delay(ms) {
return new Promise((r) => setTimeout(r, ms))
}
async function fetchWithRetry(url, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await fetch(url)
} catch (err) {
if (i === attempts - 1) throw err
await delay(2 ** i * 100)
}
}
}
Common Mistakes
- Forgetting to
returna promise inside.then, breaking the chain - Unhandled rejections—always attach
.catch()or useasync/awaitwith try/catch - Assuming
Promise.allruns sequentially—it runs in parallel - Creating promises without settling them (missing resolve/reject)
See Also
async-await fetch-api functions closures