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

SectionTopicKey Files
16.1Promise Combinators01-promise-all.js, 02-race-any.js
16.2Error Handling01-error-propagation.js, 02-recovery.js
16.3Async Patterns01-retry.js, 02-debounce-throttle.js
16.4Web Workers01-dedicated-worker.js, worker.js
16.5Async Iterators01-async-generators.js, 02-streams.js
16.6Advanced Errors01-global-handlers.js, 02-aggregation.js
16.7Cancellation01-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


🎯 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                                           │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
Module 16 Advanced Async - JavaScript Tutorial | DeepML