Advanced Async Patterns
50 minBeyond basic `async/await`, real-world applications require more sophisticated patterns to handle concurrency and complex flows.
**Promise Combinators** are essential tools: `Promise.all()` runs tasks in parallel and fails fast; `Promise.allSettled()` waits for all regardless of outcome; `Promise.race()` takes the first result; and `Promise.any()` takes the first success.
**Async Iterators and Generators** (`for await...of`) allow you to process streams of data asynchronously, which is perfect for handling large datasets or paginated APIs chunk by chunk.
**Cancellation** is a common requirement (e.g., user navigates away). The `AbortController` API provides a standard way to cancel fetch requests and other async tasks.
Key Concepts
- Parallelism with `Promise.all`.
- Resilience with `Promise.allSettled`.
- Async Generators (`async function*`).
- Async Iteration (`for await...of`).
- Task Cancellation (`AbortController`).
Learning Objectives
Master
- Optimizing performance with parallel requests
- Handling partial failures in batch operations
- Implementing cancellable async tasks
- Processing data streams efficiently
Develop
- System design thinking (concurrency)
- Resource management
- User experience (loading states/cancellation)
Tips
- Use `Promise.allSettled()` instead of `Promise.all()` when you want to show partial results even if some requests fail.
- Use `Promise.race()` to implement timeouts for network requests.
- Pass the `AbortSignal` to your fetch requests to enable cancellation.
- Don't await inside a loop unless the iterations depend on each other (sequential vs. parallel).
Common Pitfalls
- Using `Promise.all()` when one failure should not kill the entire batch.
- Forgetting to handle rejections in `Promise.race()` (it can race to a failure too!).
- Creating thousands of promises at once (concurrency limit issues); use a pool or queue instead.
- Ignoring the `AbortError` when cancelling (it's an exception you need to catch).
Summary
- Combinators control concurrency.
- Async iterators handle streams.
- AbortController enables cancellation.
- Advanced patterns solve complex flows.
Exercise
Use Promise.all() to fetch multiple resources simultaneously.
const urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2'
];
Promise.all(urls.map(url => fetch(url)))
.then(responses => Promise.all(responses.map(r => r.json())))
.then(data => console.log(data));
Exercise Tips
- Compare Promise.all() with Promise.allSettled() to see the difference in error handling.
- Try using async/await syntax instead of .then() chains.
- Add error handling with .catch() to handle network failures.
- Experiment with Promise.race() to see which request completes first.