Prior to ECMAScript 2022, the await keyword could only be executed inside functions marked with the async keyword. This forced developers to write awkward Immediately Invoked Async Function Expressions (IIAFE) to initialize databases or fetch remote configurations. With Top-Level Await, ES Modules can await promises directly at the root level of the module.
1. The Historical Workaround vs. Modern Top-Level Await
The Legacy Problem (IIAFE Boilerplate):
JavaScript
1// LEGACY: Required async wrapping function!
2let dbConnection;
3
4(async()=>{
5 dbConnection =awaitconnectToDatabase();
6})();
7
8export{ dbConnection };// DANGER: Consumer may import dbConnection before promise resolves!
4. Critical Warnings: Deadlocks and Waterfall Traps
1
Avoid Circular Top-Level Awaits: If Module X awaits an import from Module Y, and Module Y awaits an import from Module X, a circular dependency deadlock occurs.
2
Beware of Long Network Delays: A slow top-level await blocks the evaluation of every downstream module that imports it, delaying application startup.
Interactive Quiz• Knowledge Check
Practice Quiz
Question 1
In what environment is Top-Level Await valid?
Question 2
What happens to a module that imports another module containing a top-level await?
Question 3
How do sibling modules with top-level await behave when imported together?
Question 4
What common legacy workaround did top-level await replace?
Question 5
What is a key performance risk of using top-level await for slow network calls?
Next Lesson
Microtasks vs Macrotasks (Event Loop Deep Dive)
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.