Understanding how JavaScript's async model evolved helps you appreciate why we write code the way we do today.
Era 1: Callbacks (2009)
Problems: Deep nesting, error handling at every level, impossible to reason about flow.
Era 2: Promises (2015 - ES6)
Improvement: Flat chain, centralized error handling. But still not intuitive for complex flows.
Era 3: Async/Await (2017 - ES8)
Reads like synchronous code. Error handling with try/catch. Easy to debug with breakpoints.
Common Async/Await Mistakes
Sequential When Parallel Is Possible
Forgetting Error Handling
Async in forEach
Top-Level Await
ES2022 allows await at the module top level — no need for async IIFE wrappers.