В минулій статті я описував нові ключові слова в JavaScript: async та await і для чого вони потрібні. Тепер настав час дізнатися про декілька неочевидних, але важливих аспектів роботи з ними.
Функції, що використовують await мають бути позначені як async
Якщо функція виконує якийсь асинхронний код, не важливо, чи це async-функція чи звичайна функція, що повертає проміс, з використанням await, то вона теж повинна бути позначена як async.
async function getData() {
// Повертає проміс
return api.promiseGet('/data')
}
function consumeData() {
const data = await getData()
// ✘ consumeData використовує await, тому повинна теж бути асинхронною
}
// Спробуємо ще раз
async function consumeData() {
const data = await getData()
// ✔ Так краще
}
В вас може виникнути питання: а хіба тоді не потрібно всі функції рівнями вище теж робити асинхронними? Як тоді запустити початкову функцію зі звичайного коду?
Я відповім. Якщо коротко, то ви можете перервати цей ланцюжок async'ів. Це напряму повязано з другою особливістю async-функцій, адже...
Все це всього лише проміс
Функції, що позначені як async завжди повертають Promise. Та й сам синтаксис async/await - лише обгортка над промісами. Тому коли ви пишете це:
try {
const data = await doPromiseActivity()
consume(data)
} catch (err) {
handle(err)
}
JavaScript сприймає це як
doPromiseActivity()
.then(data => consume(data))
.catch(err => handle(err))
Це лише зовнішнім виглядом async/await нагадує синхронний код, під капотом все куди складніше. Тому не слід сприймати async-функції та звичайні функції, що повертають проміс як щось різне. Вони однакові:
- Всі async-функції повертають
Promise
- Всі функції, що повертають
Promise
, можуть викликатися зawait
Перший пункт дуже важливий. Розглянемо наступний код:
function getUsername() {
return 'Jack'
}
Абсолютно синхронний код. Але ми все ж можемо зробити його async:
async function getUsername() {
return 'Jack'
}
Зауважте, що функція не виконує ніяких асинхронних дій, вона всього лише повертає "Jack". Точніше, вона повертає проміс, з якого ми потім отримуємо наше ім'я. Ви можете повертати проміси зі своїх асинхронних функцій, але це не обов'язково: return
в async-функціях автоматично обгортається в проміс.
Тепер в нас є два способи працювати з даними, що віддає проміс:
async function sayHello() {
const username = await getUsername()
console.log(`Hello, ${username}!`)
}
// Або так
function sayHello() {
getUsername().then(username => {
console.log(`Hello, ${username}!`)
})
}
TL;DR: async/await дозволяє використовувати переваги асинхронного виконання коду, використовуючи при цьому звичний, схожий на синхронний, код.
Ще немає коментарів