β³ Async Programming β
Writing correct and performant asynchronous code.
Promises and async/await β
typescript
// Sequential β each waits for the previous
const user = await getUser(id)
const orders = await getOrders(user.id)
const payments = await getPayments(orders)
// Parallel β independent operations at the same time
const [user, products, settings] = await Promise.all([
getUser(id),
getProducts(),
getSettings(),
])Promise combinators β
| Method | Behavior |
|---|---|
Promise.all | Resolves when ALL resolve; rejects on first rejection |
Promise.allSettled | Waits for all; returns status of each |
Promise.race | Resolves/rejects with the first to settle |
Promise.any | Resolves with first success; rejects if all fail |
Error handling β
typescript
// Always handle rejections
try {
const data = await fetchData()
} catch (error) {
// Handle specific errors
if (error instanceof NetworkError) {
// retry logic
}
throw error // re-throw if can't handle
}Common patterns β
Retry with backoff β
typescript
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn()
} catch (error) {
if (i === maxRetries - 1) throw error
await sleep(Math.pow(2, i) * 1000) // exponential backoff
}
}
throw new Error('Unreachable')
}Concurrency limit β
typescript
// Process 10 items at a time, not all at once
import pLimit from 'p-limit'
const limit = pLimit(10)
const results = await Promise.all(
items.map(item => limit(() => processItem(item)))
)Anti-patterns β
awaitinside a loop when operations are independent- Missing error handling on promises (unhandled rejection)
- Mixing callbacks and promises
- Creating a promise in a function that's already async
- Not using
Promise.allfor independent parallel work - Fire-and-forget without error handling