Suggest an editImprove this articleRefine the answer for “What is "top-level await"?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Top-level await** is the ability to use `await` **outside** an `async` function, right at the top level of an ES module. **Key point:** the module becomes asynchronous "by nature" - its execution pauses until the `await` resolves, and other modules that import it wait for it to finish too.Shown above the full answer for quick recall.Answer (EN)Image## What it was like before Before `top-level await`, `await` could only be used **inside** an `async` **function**: ```javascript // An error before const data = await fetch('/api/data'); // Works async function main() { const data = await fetch('/api/data'); console.log(await data.json()); } main(); ``` If you needed to wait for something at the start of a module, you had to create a wrapper function (`init()`, `bootstrap()`, and so on). --- ## What changed With `top-level await` you can now write: ```javascript // module.mjs or type: "module" const response = await fetch('https://api.example.com/user'); const user = await response.json(); console.log('User:', user.name); ``` The code **pauses the module's loading** until the promise resolves. This makes the module asynchronous "by nature". --- ## Where you can use it Only in **ES modules (ESM)** - that is, in files: - with the `.mjs` extension, or - in `.js`, if `package.json` has `"type": "module"`, or - in `<script type="module">` in the browser. Not in CommonJS (Node.js require). --- ## How it works internally When a bundler or runtime encounters `await` at the top level of a module: 1. The module becomes **asynchronous**. 2. Its execution pauses until the `await` resolves. 3. Other modules that **import** this module also wait for it to finish executing (through the dependency chain). --- ## Example 1 - importing with a wait ```javascript // user.mjs export const user = await fetch('/api/user').then(r => r.json()); ``` ```javascript // main.mjs import { user } from './user.mjs'; console.log('User name:', user.name); ``` Here `main.mjs` **does not start running** until `user.mjs` finishes its `await`. --- ## Example 2 - dynamic initialization ```javascript // config.mjs const env = await fetch('/env.json').then(r => r.json()); export const API_URL = env.production ? 'https://api.prod' : 'https://api.dev'; ``` The `config` module can now be imported like a regular one, and it will asynchronously fetch its own config. --- ## Example 3 - top-level await with a dynamic import ```javascript // main.mjs const lang = navigator.language.startsWith('fr') ? 'fr' : 'en'; const messages = await import(`./messages.${lang}.js`); console.log(messages.default.hello); ``` Lets you **dynamically** import a module, using async syntax without extra wrappers. --- ## Interaction with other modules If module `A` uses `await` at the top level, and module `B` imports `A`, then `B` **also waits** for `A` to finish. ```javascript // a.mjs console.log('A start'); await new Promise(r => setTimeout(r, 1000)); console.log('A done'); // b.mjs import './a.mjs'; console.log('B start'); ``` Output: ```javascript A start A done B start ``` --- ## Advantages It simplifies module initialization (no `async init()` wrapper needed). It removes the "import pyramid" for asynchronous dependencies. It allows flexible asynchronous imports (`await import()`). --- ## Potential downsides Blocking the module chain: if one module "hangs" on a long `await`, the whole dependency tree waits for it to finish. It cannot be used in CommonJS (ESM only). It can affect the application's startup time (especially in Node JS). --- ## Example in Node.js ```javascript // package.json { "type": "module" } ``` ```javascript // index.js import fs from 'fs/promises'; const config = JSON.parse(await fs.readFile('./config.json', 'utf-8')); console.log('Config:', config); ``` This works because Node JS supports top-level await in ESM mode. --- ## Summary | Feature | Description | |---|---| | What it does | Lets you use `await` outside `async` functions | | Where it works | Only in ES modules | | What it returns | The module becomes asynchronous (returns a promise on import) | | Use cases | Asynchronous initialization, dynamic imports | | Risks | Blocks module loading, cannot be used in CommonJS |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.