Docs
Module-16-Advanced-Async
Module 16: Advanced Asynchronous JavaScript
Master advanced asynchronous programming patterns for building robust, scalable, and performant JavaScript applications.
╔═══════════════════════════════════════════════════════════════════════════════╗
║ ║
║ ┌─────────────────────────────────────────────────────────────────┐ ║
║ │ ADVANCED ASYNC JAVASCRIPT │ ║
║ │ │ ║
║ │ "Concurrency is about dealing with lots of things at once. │ ║
║ │ Parallelism is about doing lots of things at once." │ ║
║ │ - Rob Pike │ ║
║ └─────────────────────────────────────────────────────────────────┘ ║
║ ║
║ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ║
║ │ COMBINE │ │ HANDLE │ │ PATTERN │ │ CANCEL │ ║
║ │ ───────── │ │ ───────── │ │ ───────── │ │ ───────── │ ║
║ │ Promise.all │ │ Retries │ │ Streams │ │ Abort │ ║
║ │ .race │ │ Timeouts │ │ Iteration │ │ Controller │ ║
║ │ .any │ │ Recovery │ │ Workers │ │ Cleanup │ ║
║ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════════╝
📋 Module Overview
This module takes you beyond basic Promises and async/await into the realm of production-grade async programming. You'll learn to handle complex scenarios like parallel execution, graceful error recovery, and cancellation.
┌─────────────────────────────────────────────────────────────────────────────┐
│ FROM BASIC TO ADVANCED ASYNC │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Basic: Advanced: │
│ ────── ───────── │
│ │
│ const data = await fetch(url); const results = await Promise.all([ │
│ fetch(url1), │
│ fetch(url2), │
│ fetch(url3) │
│ ]); │
│ │
│ try { async function fetchWithRetry(url) { │
│ await doSomething(); for (let i = 0; i < 3; i++) { │
│ } catch (err) { try { │
│ console.error(err); return await fetch(url); │
│ } } catch (e) { │
│ await delay(1000 * 2 ** i); │
│ } │
│ } │
│ throw new Error('Failed'); │
│ } │
│ │
│ Sequential: Parallel: │
│ const a = await fetch(url1); const [a, b, c] = await Promise.all([ │
│ const b = await fetch(url2); fetch(url1), │
│ const c = await fetch(url3); fetch(url2), │
│ // Takes: 3 × time fetch(url3) │
│ ]); │
│ // Takes: max(time1, time2, time3) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
🎯 Learning Objectives
By the end of this module, you will be able to:
┌─────────────────────────────────────────────────────────────────────────────┐
│ SKILL PROGRESSION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Level 1: Parallel Execution │
│ ├── Execute multiple async operations in parallel │
│ ├── Choose the right Promise combinator for each situation │
│ └── Understand settle vs reject behavior │
│ │
│ Level 2: Error Management │
│ ├── Handle complex error scenarios │
│ ├── Implement retry logic with backoff │
│ └── Design graceful degradation strategies │
│ │
│ Level 3: Advanced Patterns │
│ ├── Implement debouncing and throttling │
│ ├── Build timeout mechanisms │
│ └── Create async queues and pools │
│ │
│ Level 4: Production Readiness │
│ ├── Create cancellable async operations │
│ ├── Stream data with async iterators │
│ └── Build real-world async utilities │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
📋 Prerequisites
- •Module 15: Asynchronous JavaScript - Promises, async/await
- •Module 12: Execution Context - Event loop understanding
- •Module 13: Modern JavaScript - Generators basics
📚 Sections
16.1 Promise Combinators
┌─────────────────────────────────────────────────────────────────────────────┐
│ PROMISE COMBINATORS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Promise.all([p1, p2, p3]) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ p1: ████████████████──────────────────────────────► ✓ │ │
│ │ p2: ████████████████████████████──────────────────► ✓ │ │
│ │ p3: ████████████████████████████████████████──────► ✓ │ │
│ │ ────────────────────────────────────────────────► │ │
│ │ Returns: [r1, r2, r3] │ │
│ │ If ANY fails: ██████████████──────────────► ✗ (rejects immediately)│ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Promise.allSettled([p1, p2, p3]) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ p1: ████████████████──────────────────────────────► ✓ │ │
│ │ p2: ██████████████────────────────────────────────► ✗ (no problem!)│ │
│ │ p3: ████████████████████████████████████████──────► ✓ │ │
│ │ ────────────────────────────────────────────────► │ │
│ │ Returns: [{status, value/reason}, ...] │ │
│ │ ALWAYS resolves, never rejects │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Promise.race([p1, p2, p3]) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ p1: ████████████████████████████████████████──────► (too slow) │ │
│ │ p2: ████████──────────────────────────────────────► ✓ WINNER! │ │
│ │ p3: ████████████████████████──────────────────────► (too slow) │ │
│ │ ──────────► │ │
│ │ ↑ Returns FIRST to settle (fulfill OR reject) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Promise.any([p1, p2, p3]) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ p1: ██████────────────────────────────────────────► ✗ (ignored) │ │
│ │ p2: ████████████████────────────────────────────► ✓ WINNER! │ │
│ │ p3: ████████████────────────────────────────────► ✗ (ignored) │ │
│ │ ──────────────────► │ │
│ │ ↑ Returns FIRST to FULFILL (ignores rejections) │ │
│ │ │ │
│ │ If ALL fail: → AggregateError (collection of all errors) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
- •Promise.all() - Parallel execution, fail-fast
- •Promise.allSettled() - Get all results regardless of failures
- •Promise.race() - First to settle wins
- •Promise.any() - First to fulfill wins
16.2 Advanced Error Handling
┌─────────────────────────────────────────────────────────────────────────────┐
│ ERROR HANDLING STRATEGIES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Error Propagation: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ async function level3() { │ │
│ │ throw new Error('Deep error'); ──┐ │ │
│ │ } │ │ │
│ │ │ propagates up │ │
│ │ async function level2() { │ │ │
│ │ await level3(); ◄─────────────────┘ │ │
│ │ } ──┐ │ │
│ │ │ propagates up │ │
│ │ async function level1() { │ │
│ │ try { │ │ │
│ │ await level2(); ◄┘ │ │
│ │ } catch (err) { │ │
│ │ console.log('Caught:', err); ◄── Handled here! │ │
│ │ } │ │
│ │ } │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Recovery Patterns: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ async function fetchWithFallback() { │ │
│ │ try { │ │
│ │ return await primarySource(); // Try primary │ │
│ │ } catch { │ │
│ │ return await backupSource(); // Fall back │ │
│ │ } │ │
│ │ } │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
- •Error propagation - How errors bubble through async code
- •Global error handlers - window.onerror, unhandledrejection
- •Error recovery patterns - Fallbacks and retries
- •Graceful degradation - Partial success handling
16.3 Async Patterns
┌─────────────────────────────────────────────────────────────────────────────┐
│ ASYNC PATTERNS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Retry with Exponential Backoff: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Attempt 1: ██ → ✗ │ │
│ │ └── Wait 1 second │ │
│ │ Attempt 2: ████ → ✗ │ │
│ │ └── Wait 2 seconds │ │
│ │ Attempt 3: ████████ → ✗ │ │
│ │ └── Wait 4 seconds │ │
│ │ Attempt 4: ████████████████ → ✓ Success! │ │
│ │ │ │
│ │ delay = baseDelay * (2 ^ attemptNumber) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Timeout Pattern: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ function timeout(promise, ms) { │ │
│ │ const timer = new Promise((_, reject) => { │ │
│ │ setTimeout(() => reject(new Error('Timeout')), ms); │ │
│ │ }); │ │
│ │ return Promise.race([promise, timer]); │ │
│ │ } │ │
│ │ │ │
│ │ await timeout(fetch(url), 5000); // 5 second timeout │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Throttle vs Debounce: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Events: ║ ║║ ║ ║║║║ ║ ║ ║║║ │ │
│ │ │ │
│ │ Throttle: ║ ║ ║ ║ (At most once per interval) │ │
│ │ │ │
│ │ Debounce: ║ (Only after silence) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
- •Retry with exponential backoff - Smart failure recovery
- •Timeout handling - Don't wait forever
- •Debouncing and throttling - Rate limiting
- •Sequential vs parallel execution - When to use each
16.4 Web Workers
┌─────────────────────────────────────────────────────────────────────────────┐
│ WEB WORKERS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Main Thread Worker Thread │
│ ───────────── ───────────── │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ │ postMessage │ │ │
│ │ UI + │ ──────────────────► │ Heavy │ │
│ │ Events │ │ Computation │ │
│ │ │ ◄────────────────── │ │ │
│ │ │ postMessage │ │ │
│ └──────────────┘ └──────────────┘ │
│ │ │ │
│ │ UI stays │ CPU-intensive │
│ │ responsive! │ work here │
│ │
│ // main.js // worker.js │
│ const worker = new Worker( self.onmessage = (e) => { │
│ 'worker.js' const result = heavyCalc(e.data); │
│ ); self.postMessage(result); │
│ worker.postMessage(data); }; │
│ worker.onmessage = (e) => { │
│ console.log(e.data); │
│ }; │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
- •Dedicated Workers - Background threads
- •Shared Workers - Shared between tabs
- •Service Workers - Offline and caching
- •Worker communication - postMessage, Transferable
16.5 Async Iterators & Streams
┌─────────────────────────────────────────────────────────────────────────────┐
│ ASYNC ITERATION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Async Generator: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ async function* fetchPages(url) { │ │
│ │ let page = 1; │ │
│ │ while (true) { │ │
│ │ const response = await fetch(`${url}?page=${page}`); │ │
│ │ const data = await response.json(); │ │
│ │ if (data.length === 0) break; │ │
│ │ yield data; ◄── Yield and pause │ │
│ │ page++; │ │
│ │ } │ │
│ │ } │ │
│ │ │ │
│ │ // Consuming │ │
│ │ for await (const page of fetchPages('/api/items')) { │ │
│ │ console.log(page); ◄── Resume and get next │ │
│ │ } │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Stream Flow: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Source ──► [chunk] ──► [chunk] ──► [chunk] ──► Consumer │ │
│ │ │ │ │ │ │
│ │ └─────┬─────┴─────┬─────┘ │ │
│ │ │ │ │ │
│ │ Transform Transform │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
- •for await...of loops - Iterate over async data
- •Async generators - yield with await
- •Streaming data - Process large data incrementally
- •Pagination patterns - Lazy loading data
16.6 Advanced Error Handling
More patterns for robust error handling in async code.
16.7 AbortController & Cancellation
┌─────────────────────────────────────────────────────────────────────────────┐
│ CANCELLATION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ AbortController Flow: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ const controller = new AbortController(); │ │
│ │ const signal = controller.signal; │ │
│ │ │ │
│ │ // Start operation │ │
│ │ fetch(url, { signal }) │ │
│ │ .then(response => response.json()) │ │
│ │ .catch(err => { │ │
│ │ if (err.name === 'AbortError') { │ │
│ │ console.log('Cancelled!'); │ │
│ │ } │ │
│ │ }); │ │
│ │ │ │
│ │ // Later: cancel the operation │ │
│ │ controller.abort(); │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ signal.aborted = true │ │ │
│ │ │ 'abort' event fires │ │ │
│ │ │ fetch() rejects │ │ │
│ │ └─────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Use Cases: │
│ ├── Cancel fetch on component unmount │
│ ├── Cancel previous search when user types new query │
│ ├── Timeout with cancellation │
│ └── User-initiated cancel buttons │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
- •AbortController API - Modern cancellation
- •Cancellable promises - Wrapping operations
- •Cleanup on cancellation - Resource management
- •Timeout with cancellation - Time-limited operations
🔑 Key Concepts Summary
┌─────────────────────────────────────────────────────────────────────────────┐
│ COMBINATOR QUICK REFERENCE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Combinator │ Resolves When │ Rejects When │
│ ───────────────────│─────────────────────│─────────────────────────────── │
│ Promise.all │ ALL fulfill │ ANY rejects (fail-fast) │
│ Promise.allSettled │ ALL settle │ NEVER rejects │
│ Promise.race │ FIRST settles │ FIRST rejects (if first) │
│ Promise.any │ FIRST fulfills │ ALL reject (AggregateError) │
│ │
│ Pattern │ Use Case │ Example │
│ ───────────────────│─────────────────────│─────────────────────────────── │
│ Retry + backoff │ Network failures │ API calls, webhooks │
│ Timeout │ Prevent hanging │ fetch(), external services │
│ Debounce │ User input │ Search, autocomplete │
│ Throttle │ Frequent events │ Scroll, resize handlers │
│ Cancellation │ User navigation │ SPA route changes, cleanup │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
💡 Common Patterns
Parallel with Timeout
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
return await response.json();
} finally {
clearTimeout(timeoutId);
}
}
Retry with Exponential Backoff
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fetch(url);
} catch (err) {
if (i === maxRetries - 1) throw err;
await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, i)));
}
}
}
Concurrent with Limit
async function mapWithLimit(items, limit, fn) {
const results = [];
const executing = new Set();
for (const item of items) {
const promise = fn(item).then((result) => {
executing.delete(promise);
return result;
});
executing.add(promise);
results.push(promise);
if (executing.size >= limit) {
await Promise.race(executing);
}
}
return Promise.all(results);
}
📚 Section Files
| Section | Topic | Key Files |
|---|---|---|
| 16.1 | Promise Combinators | 01-promise-all.js, 02-race-any.js |
| 16.2 | Error Handling | 01-error-propagation.js, 02-recovery.js |
| 16.3 | Async Patterns | 01-retry.js, 02-debounce-throttle.js |
| 16.4 | Web Workers | 01-dedicated-worker.js, worker.js |
| 16.5 | Async Iterators | 01-async-generators.js, 02-streams.js |
| 16.6 | Advanced Errors | 01-global-handlers.js, 02-aggregation.js |
| 16.7 | Cancellation | 01-abort-controller.js, 02-timeout.js |
⚠️ Common Pitfalls
┌─────────────────────────────────────────────────────────────────────────────┐
│ ASYNC PITFALLS TO AVOID │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ❌ Ignoring Promise.race cleanup │
│ ──────────────────────────────── │
│ Promise.race([fetch(url), timeout(5000)]); │
│ // ⚠️ If timeout wins, fetch keeps running! │
│ // ✅ Use AbortController for proper cleanup │
│ │
│ ❌ Sequential when parallel is possible │
│ ───────────────────────────────────────── │
│ const a = await fetch(url1); // Waits │
│ const b = await fetch(url2); // Then waits │
│ // ✅ const [a, b] = await Promise.all([fetch(url1), fetch(url2)]); │
│ │
│ ❌ Swallowing errors │
│ ──────────────────────── │
│ promise.catch(() => {}); // Silent failure! │
│ // ✅ Log, report, or handle meaningfully │
│ │
│ ❌ Not handling partial failures │
│ ───────────────────────────────── │
│ await Promise.all(urls.map(fetch)); // One failure = all fail │
│ // ✅ Use Promise.allSettled for partial success │
│ │
│ ❌ Retry without backoff │
│ ─────────────────────── │
│ while (true) { try { await fetch(); } catch { continue; } } │
│ // ⚠️ Hammers server, uses resources │
│ // ✅ Add exponential backoff + max retries │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
🔗 Related Modules
- •Previous: Module 15 - Asynchronous JavaScript
- •Next: Module 17 - DOM Manipulation
- •Related: Module 13.5 - Generators
🎯 Learning Path
┌─────────────────────────────────────────────────────────────────────────────┐
│ RECOMMENDED ORDER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Week 1: Combinators │
│ ├── Master Promise.all and Promise.race │
│ ├── Learn Promise.allSettled for resilience │
│ └── Understand Promise.any for fallbacks │
│ │
│ Week 2: Error Handling & Patterns │
│ ├── Implement retry with backoff │
│ ├── Build timeout utilities │
│ └── Practice debounce and throttle │
│ │
│ Week 3: Advanced │
│ ├── Learn async generators │
│ ├── Implement pagination with for await...of │
│ └── Master AbortController for cancellation │
│ │
│ Week 4: Real-World │
│ ├── Build a fetch wrapper with all features │
│ ├── Create an async queue │
│ └── Implement caching with async │
│ │
└─────────────────────────────────────────────────────────────────────────────┘