JavaScript с использованием async и await

JavaScript с использованием async и await

WebDEV

Async функции представляют собой комбинацию promise и генераторов, и в основном они представляют собой абстракцию более высокого уровня над promise. Позвольте мне повторить: async/await построен на promise.


Почему был введён async/await

Когда Promises были введены в ES2015, они должны были решить проблему с асинхронным кодом, и у них это удалось, но на протяжении двух лет, которые разделяли ES2015 и ES2017, было ясно, что promises не могут быть окончательным решением задачи.

Promises были введены для решения известной проблемы callback hell, но тогда они сами породили новую сложность и сложный синтаксис.

Promises были хорошими примитивами, вокруг которых мог быть раскрыт лучший синтаксис для разработчиков, поэтому, когда подошло время, мы получили async функции.

Async/await делает код похожим на синхронный, но он асинхронен и не блокируется компилятором.


Как это работает

Async функция возвращает promise, как на этом примере:

const doSomethingAsync = () => {
   return new Promise((resolve) => {
       setTimeout(() => resolve('I did something'), 3000)
   })
}

Когда вы вызываете эту функцию, вы ждёте (await), и вызов останавливается до тех пор, пока promise не будет разрешён или отклонён. Один нюанс: клиентская функция должна быть определена как async. Вот пример:

const doSomething = async () => {
   console.log(await doSomethingAsync())
}


Быстрый пример

Это простой пример async/await, используемый для запуска функции асинхронно:

const doSomethingAsync = () => {
   return new Promise((resolve) => {
       setTimeout(() => resolve('I did something'), 3000)
   })
}
 
const doSomething = async () => {
   console.log(await doSomethingAsync())
}
 
console.log('Before')
doSomething()
console.log('After')

Указанный выше код выведет в консоль браузера следующее:

Before
After
I did something //after 3s


Любая функция может вернуть promise

Добавление ключевого слова async в любую функцию означает, что функция обязательно вернёт promise.

Даже если это явно не так, компилятор заставит функцию сделать это.

Вот почему этот код будет работать:

const aFunction = async () => {
 return 'test'
}
aFunction().then(alert) // This will alert 'test'

это то же самое, что:

const aFunction = async () => {
 return Promise.resolve('test')
}
aFunction().then(alert) // This will alert 'test'


Код намного проще читать

Как вы можете видеть в приведённом выше примере, наш код выглядит очень просто. Сравните его с кодом, в котором используются простые promise или callback.

Приведённый выше пример очень простой, основные преимущества будут видны, когда код станет намного сложнее.

Для примера, мы получим ресурс JSON и проанализируем его, используя promise:

const getFirstUserData = () => {
 return fetch('/users.json') // получить список users
   .then(response => response.json()) // parse JSON
   .then(users => users[0]) // выбрать первого user
   .then(user => fetch(`/users/${user.name}`)) // получить информацию о user
   .then(userResponse => response.json()) // parse JSON
}
getFirstUserData()

И сделаем то же самое, но уже при помощи async/await:

const getFirstUserData = async () => {
 const response = await fetch('/users.json') // получить список users
 const users = await response.json() // parse JSON
 const user = users[0] // выбрать первого user
 const userResponse = await fetch(`/users/${user.name}`) // получить информацию о user
 const userData = await user.json() // parse JSON
 return userData
}
getFirstUserData()


Несколько async функций последовательно

Написать async функцию очень легко, и её синтаксис гораздо читабельнее, чем у обычного promise:

const promiseToDoSomething = () => {
   return new Promise(resolve => {
       setTimeout(() => resolve('I did something'), 10000)
   })
}
 
const watchOverSomeoneDoingSomething = async () => {
   const something = await promiseToDoSomething()
   return something + ' and I watched'
}
 
const watchOverSomeoneWatchingSomeoneDoingSomething = async () => {
   const something = await watchOverSomeoneDoingSomething()
   return something + ' and I watched as well'
}
 
watchOverSomeoneWatchingSomeoneDoingSomething().then((res) => {
   console.log(res)
})

Будет выведено:

I did something and I watched and I watched as well


Лёгкая отладка

Отладка promise может вызвать затруднение, потому что отладчик не будет переходить на асинхронный код.

С async/await сделать это гораздо проще, потому что для компилятора эти функции похожи на синхронный код.


Report Page