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.”