Skip to content

20 — Callback Chains and Callback Hell

rebeloper edited this page Jul 12, 2026 · 1 revision

🍽️ Intuition

Each station only tells the next station when it's done by shouting through to them directly. Chain enough stations together and the shouted instructions become an unreadable nested mess.

🧠 What It Means In Swift

Sequential async GCD operations are typically chained via nested completion-handler closures — each step's callback kicks off the next step. This nesting grows with each additional step, producing the classic "pyramid of doom."

📊 ASCII Diagram

fetchData {
  parse {
    save {
      updateUI {
      }
    }
  }
}

💻 Tiny Swift Example

fetchData { data in
    parse(data) { parsed in
        save(parsed) { success in
            DispatchQueue.main.async {
                updateUI(success)
            }
        }
    }
}

🔄 vs. Swift Concurrency

Sequential await calls read top-to-bottom like synchronous code, flattening the pyramid entirely:

let data = await fetchData()
let parsed = await parse(data)
let success = await save(parsed)
await updateUI(success)

🧸 Memory Sentence

Callback chains are instructions shouted station to station — await just reads the recipe top to bottom.

⚠️ Analogy Limit

Real stations shouting to each other don't get exponentially harder to follow the way deeply nested closures do on screen — the code readability cost is a purely technical problem, not a kitchen one.

✅ Check Your Understanding

What specifically makes the nested-closure version harder to read than the await version?

Clone this wiki locally