Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «await у стрілкових функціях». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Так, `await` у стрілковій функції працює, але тільки якщо ця стрілка оголошена як `async`.** `await`, це оператор, дозволений лише всередині `async`-функції або на верхньому рівні ES-модуля (top-level await). Стрілкова функція нічим не особлива: `async () => {}` дає таку саму асинхронну функцію, як і `async function`, і так само завжди повертає проміс, навіть якщо всередині немає жодного `await`. Без ключового слова `async` рушій навіть не почне виконувати код: він упаде на етапі парсингу з `SyntaxError: await is only valid in async functions`. Так само легально писати `async`-стрілку як колбек, наприклад усередині `.then()` або `map()`. ```javascript const fetchData = async () => { const data = await Promise.resolve('Done'); console.log(data); // Done }; ``` **Ключове:** `await` дозволяє не стрілка, а `async` перед нею; `async`-стрілка завжди повертає проміс.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Так, `await` у стрілковій функції використовувати можна, але лише тоді, коли стрілка оголошена з ключовим словом `async`.** Сама форма запису функції тут ні до чого: дозвіл на `await` дає `async`, а не стрілка чи `function`. ## Теорія ### TL;DR - `await` дозволений лише всередині `async`-функції або на верхньому рівні ES-модуля. - Стрілкова функція стає асинхронною так само просто: `async () => { ... }`. - Без `async` це `SyntaxError`, код не виконається взагалі, бо помилка виникає ще під час парсингу. - Будь-яка `async`-функція, зокрема стрілкова, завжди повертає проміс. - `async`-стрілку можна передавати як колбек, наприклад у `.then()`, і `await` усередині неї цілком легальний. - Поза функцією `await` працює тільки як top-level await в ESM. ### Швидкий приклад ```javascript const fetchData = async () => { const data = await Promise.resolve('Готово'); console.log(data); }; fetchData(); ``` Результат: ```text Готово ``` `async` перед стрілковою функцією перетворює її на асинхронну функцію, яка завжди повертає проміс. ### Де взагалі дозволений await `await`, це оператор, який можна вживати тільки в двох місцях: - усередині функції, оголошеної з `async`; - на верхньому рівні модуля (top-level await). Якщо використати `await` поза `async`, буде синтаксична помилка: ```javascript // Помилка const result = await Promise.resolve(42); // SyntaxError: await is only valid in async functions ``` Те саме зі звичайною стрілкою без `async`: ```javascript const foo = () => { const data = await Promise.resolve('value'); console.log(data); }; // SyntaxError: await is only valid in async functions ``` Зверніть увагу: це не помилка часу виконання. JS навіть не почне виконувати код, бо `await` неприпустимий у звичайній функції, і скрипт падає ще на етапі розбору. ### Що повертає async-стрілка `async`-стрілка завжди повертає проміс, навіть якщо в ній немає жодного `await`: ```javascript const sum = async (a, b) => a + b; console.log(sum(1, 2)); // Promise { 3 } ``` Це те саме, що написати: ```javascript function sum(a, b) { return Promise.resolve(a + b); } ``` Тому результат такої функції треба або `await`-ити, або обробляти через `.then()`. ### Різні форми запису Стрілка з `await` у звичайному вигляді: ```javascript const loadUser = async () => { const res = await fetch('/api/user'); return res.json(); }; ``` З параметрами: ```javascript const getUser = async (id) => { const res = await fetch(`/api/user/${id}`); return res.json(); }; ``` Багаторядкова форма: ```javascript const processData = async () => { const data = await fetch('/api/data'); const json = await data.json(); console.log(json); }; ``` У ланцюжку промісів: ```javascript Promise.resolve('A') .then(async (x) => { const y = await Promise.resolve('B'); return x + y; }) .then(console.log); // "AB" ``` Тут `then()` приймає async-стрілкову функцію, і `await` усередині неї повністю легальний: `then` просто дочекається промісу, який ця функція поверне. ### Top-level await Сучасні JS-модулі (ESM) дозволяють використовувати `await` поза функціями, якщо код виконується саме як модуль, а не як звичайний `<script>` без `type="module"`: ```javascript // main.js const data = await fetch('/api/data').then(r => r.json()); console.log(data); ``` Це і є top-level await. Він працює лише в ESM (у браузері з `<script type="module">` або в Node.js з `"type": "module"` у `package.json`). У CommonJS-модулі такий код не запрацює. > Проста аналогія: `async` перед стрілковою функцією, це перепустка, яка дає право вживати `await` усередині. Без неї рушій просто не знає, куди повертати результат очікування. ### Підсумкова таблиця | Питання | Відповідь | | --- | --- | | Чи можна вживати `await` у стрілковій функції? | Так, якщо вона оголошена як `async` | | Що буде без `async`? | `SyntaxError: await is only valid in async functions` | | Що повертає `async`-стрілка? | Завжди `Promise` | | Чи можна `await` у `.then()` або колбеках? | Так, якщо колбек оголошений як `async` | | Чи можна `await` поза функцією? | Тільки як top-level await у модулях | ### Типові помилки - Ставити `await` у звичайній стрілці й дивуватися, що не працює навіть код до нього: це помилка парсингу, а не виконання. - Забувати, що `async`-стрілка повертає проміс, і писати `const x = sum(1, 2)`, отримуючи `Promise`, а не число. - Писати `async` на зовнішній функції, а `await` використовувати всередині вкладеного звичайного колбека, наприклад `arr.forEach(item => { await save(item); })`. Помічати треба саме той колбек: `async item => ...`. - Чекати, що `arr.forEach(async ...)` дочекається всіх операцій: `forEach` ігнорує повернені проміси, потрібен `for...of` з `await` або `Promise.all(arr.map(async ...))`. - Використовувати top-level await у файлі, який завантажується як звичайний скрипт або як CommonJS: там він недоступний.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.