Top-level Await Modules in JavaScript
🚀 What is Top-level Await?
Top-level await allows you to use the await keyword *outside* of async functions — directly at the top level of ES modules. It simplifies working with asynchronous code by eliminating the need to wrap logic in an async function. 🌈
Note
⚠️ Top-level await only works inside JavaScript modules (not in scripts).
🛠️ Syntax
Using await at the module level
// This is a valid ES module
const data = await fetch('/api/data').then(res => res.json());
console.log(data); // Works without an async function📁 Module Context Required
To use top-level await, the JavaScript file must be treated as a module. You can do this by either:
- Adding type="module" in your HTML script tag
- Saving the file with .mjs extension (for Node.js)
In HTML
<script type="module" src="app.js"></script>🌐 Real Example
Top-level Await in ES Module
// app.js
const res = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await res.json();
console.log(users);Note
💡 You no longer need IIFEs or async wrapper functions to use await at the module scope!
🔄 Use in Module Imports
You can also await the result of a dynamic import directly:
Await dynamic import
const math = await import('./math.js');
console.log(math.add(5, 3));🤯 Use Case: Sequential Module Execution
Top-level await pauses the module loading until the awaited promise resolves, which can help control the execution order.
Load config before app runs
const config = await fetch('/config.json').then(r => r.json());
initializeApp(config);Note
🧠 Modules that depend on top-level await become asynchronous modules — and other modules importing them must wait for them to finish executing.
⛔ Be Careful With Circular Dependencies
If you have two modules that import each other and both use top-level await, it can lead to deadlocks or loading issues. 🔁
✅ When to Use It
- Fetching configuration or data before bootstrapping the app 🧾
- Dynamically importing large modules only when needed 🧩
- Ensuring sequential script execution in modules 📐
📚 References
>>“With top-level await, async code feels just like sync code.”