Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке "top-level await"?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Top-level await** - це можливість використовувати `await` **поза** `async`-функцією, прямо на верхньому рівні ES-модуля. **Ключове:** модуль стає асинхронним "за своєю природою" - його виконання призупиняється, поки не виконається `await`, а інші модулі, що його імпортують, теж чекають на завершення.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що було раніше До `top-level await` використовувати `await` можна було **лише всередині** `async`**-функції**: ```javascript // Помилка раніше const data = await fetch('/api/data'); // Працює async function main() { const data = await fetch('/api/data'); console.log(await data.json()); } main(); ``` Якщо потрібно було дочекатися чогось на початку модуля, доводилося створювати функцію-обгортку (`init()`, `bootstrap()` тощо). --- ## Що змінилося З `top-level await` тепер можна писати: ```javascript // module.mjs або type: "module" const response = await fetch('https://api.example.com/user'); const user = await response.json(); console.log('Користувач:', user.name); ``` Код **призупиняє завантаження модуля**, поки проміс не виконається. Це робить модуль асинхронним "за своєю природою". --- ## Де можна використовувати Лише в **ES-модулях (ESM)** - тобто у файлах: - з розширенням `.mjs`, або - у `.js`, якщо в `package.json` вказано `"type": "module"`, або - у `<script type="module">` в браузері. У CommonJS (Node.js require) - не можна. --- ## Як це працює під капотом Коли збирач або рантайм зустрічає `await` на верхньому рівні модуля: 1. Модуль стає **асинхронним**. 2. Його виконання призупиняється, поки не виконається `await`. 3. Інші модулі, які **імпортують** цей модуль, теж чекають, поки він завершить виконання (через ланцюжок залежностей). --- ## Приклад 1 - імпорт з очікуванням ```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); ``` Тут `main.mjs` **не почне виконуватися**, поки `user.mjs` не виконає свій `await`. --- ## Приклад 2 - динамічна ініціалізація ```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'; ``` Модуль `config` тепер можна імпортувати як звичайний, а він сам асинхронно підтягне конфіг. --- ## Приклад 3 - top-level await з динамічним імпортом ```javascript // main.mjs const lang = navigator.language.startsWith('fr') ? 'fr' : 'en'; const messages = await import(`./messages.${lang}.js`); console.log(messages.default.hello); ``` Дозволяє **динамічно** імпортувати модуль, використовуючи асинхронний синтаксис без зайвих обгорток. --- ## Взаємодія з іншими модулями Якщо модуль `A` використовує `await` на верхньому рівні, а модуль `B` імпортує `A`, то `B` **теж чекає**, поки `A` завершиться. ```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'); ``` Вивід: ```javascript A start A done B start ``` --- ## Переваги Спрощує ініціалізацію модулів (немає `async init()` навколо). Усуває "піраміду імпортів" для асинхронних залежностей. Дозволяє гнучко робити асинхронні імпорти (`await import()`). --- ## Потенційні мінуси Блокування ланцюжка модулів - якщо один модуль "висить" на довгому `await`, усе дерево залежностей чекає на його завершення. Не можна використовувати в CommonJS (лише ESM). Може вплинути на час старту застосунку (особливо в Node JS). --- ## Приклад у 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); ``` Працює, тому що Node JS підтримує top-level await в ESM-режимі. --- ## Підсумок | Особливість | Опис | |---|---| | Що робить | Дозволяє використовувати `await` поза `async`-функціями | | Де працює | Лише в ES-модулях | | Що повертає | Модуль стає асинхронним (повертає проміс при імпорті) | | Застосування | Асинхронна ініціалізація, динамічні імпорти | | Ризики | Блокування завантаження модулів, не можна в CommonJS |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.