📚 3 min read
Promise Patterns ​
Learn how to effectively work with Promises in JavaScript.
Basic Promise Usage ​
Create and work with Promises:
typescript
// Creating a Promise
const promise = new Promise((resolve, reject) => {
// Async operation
setTimeout(() => {
const success = true;
if (success) {
resolve('Operation completed');
} else {
reject(new Error('Operation failed'));
}
}, 1000);
});
// Using a Promise
promise
.then(result => console.log(result))
.catch(error => console.error(error));
// Async/await syntax
async function example() {
try {
const result = await promise;
console.log(result);
} catch (error) {
console.error(error);
}
}
Promise Combinators ​
Using Promise combination methods:
typescript
// Promise.all - Wait for all promises
async function fetchAllUsers(ids: number[]) {
const promises = ids.map(id => fetchUser(id));
const users = await Promise.all(promises);
return users;
}
// Promise.race - First to complete
async function fetchWithTimeout(url: string, timeout: number) {
return Promise.race([
fetch(url),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), timeout)
)
]);
}
// Promise.any - First to succeed
async function fetchFromMirrors(urls: string[]) {
return Promise.any(
urls.map(url => fetch(url))
);
}
// Promise.allSettled - Wait for all to complete
async function attemptAll(tasks: Promise<any>[]) {
const results = await Promise.allSettled(tasks);
return results.map(result => ({
status: result.status,
value: result.status === 'fulfilled' ? result.value : result.reason
}));
}
Promise Chaining ​
Chain multiple operations:
typescript
function processUser(userId: number) {
return fetchUser(userId)
.then(user => {
// Transform user data
return {
...user,
lastAccess: new Date()
};
})
.then(user => {
// Save to database
return saveUser(user);
})
.then(user => {
// Notify other services
return Promise.all([
notifyProfile(user),
notifyAnalytics(user)
]);
})
.catch(error => {
// Handle any error in the chain
console.error('Processing failed:', error);
throw error;
});
}
Custom Promise Wrappers ​
Create reusable Promise patterns:
typescript
// Retry wrapper
function withRetry<T>(
operation: () => Promise<T>,
retries = 3,
delay = 1000
): Promise<T> {
return new Promise((resolve, reject) => {
function attempt(attemptsLeft: number) {
operation()
.then(resolve)
.catch(error => {
if (attemptsLeft === 0) {
reject(error);
} else {
setTimeout(() => attempt(attemptsLeft - 1), delay);
}
});
}
attempt(retries);
});
}
// Timeout wrapper
function withTimeout<T>(
promise: Promise<T>,
timeout: number
): Promise<T> {
return Promise.race([
promise,
new Promise<T>((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), timeout)
)
]);
}
// Cache wrapper
function withCache<T>(
key: string,
operation: () => Promise<T>,
ttl = 60000
): Promise<T> {
const cache = new Map<string, { value: T; expires: number }>();
return new Promise((resolve, reject) => {
const cached = cache.get(key);
if (cached && Date.now() < cached.expires) {
resolve(cached.value);
return;
}
operation()
.then(value => {
cache.set(key, {
value,
expires: Date.now() + ttl
});
resolve(value);
})
.catch(reject);
});
}
Error Handling ​
Handle Promise errors effectively:
typescript
async function robustOperation() {
try {
// Operation that might fail
const result = await riskyOperation();
return result;
} catch (error) {
// Specific error handling
if (error instanceof NetworkError) {
// Retry network operations
return withRetry(() => riskyOperation());
}
if (error instanceof ValidationError) {
// Handle validation errors
return fallbackOperation();
}
// Unexpected errors
console.error('Unexpected error:', error);
throw error;
} finally {
// Cleanup
await cleanup();
}
}
Best Practices ​
Promise Creation
- Only create new Promises when wrapping async operations
- Avoid unnecessary Promise wrapping
- Use async/await for cleaner code
Error Handling
- Always handle Promise rejections
- Use specific error types
- Implement proper error recovery
Performance
- Use appropriate Promise combinators
- Avoid unnecessary Promise chains
- Consider caching Promise results
Code Organization
- Keep Promise chains readable
- Break down complex operations
- Document async behavior