#10 Async await в Javascript

poster
В этом видео мы с вами разберем async await из es7 и сравним, чем он лучше промисов.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В этом видео мы с вами разберем async await из es7 и сравним, чем он лучше промисов.

Сразу же напомню, что из коробки он поддерживается только в последних версиях браузеров, поэтому, если вы хотите поддерживать и старые браузеры тоже, то используете babel для транспайла кода в es5.

Что же такое async await? Это новый стиль написания асинхронного кода. До async await мы использовали промисы, а еще раньше коллбеки. Но, на самом деле, async await написан сверху промисом и хорошо с ними работает.

Зачем его вообще использовать? Async await заставляет код, который работает асинхронно, выглядеть, как синхронный код. Это именно то, ради чего его используют.

Давайте разберем примеры.

const fetchProducts = () => Promise.resolve({data: [1,2,3]})

const getProducts = () => {
  fetchProducts().then(data => {
    console.log('data', data)
  })
}

getProducts()

У нас есть функция fetchProducts, которая возвращает Promise. И функция getProducts, в которой мы ее вызываем.

Если мы посмотрим в браузер, то все работает.

Давайте попробуем этот код переписать на async/await.

const getProducts = async () => {
  console.log('data', await fetchProducts())
}

Мы просто добавляем слово async перед скобками функции, показывая, что мы хотим работать с asyn/await и внутри в месте, где мы выполняем асинхронную операцию мы пишем await и промис.

Если мы посмотрим в браузер, то все работает.

Сразу скажу, что если вы не поставили функции async, то вы не сможете использовать внутри await.

Также, как только мы написали async, то функция сразу стала возвращать promise.

console.log(getProducts())

Как мы видим в браузере, у нас вывелся промис и мы можем в любом другом месте на этот промис подписаться.

Почему код с async await лучше? Первое: потому что он короче. Второе: потому что у нас код становится плоским, что упрощает поддержку. Третье: нам намного легче избегать callback hell, когда наш код плоский.

Теперь, давайте посмотрим как хендлить ерроры в async await.

В промисах мы обычно использовали catch.

const fetchProducts = () => Promise.reject('someErr happened')

const getProducts = () => {
  fetchProducts().then(data => {
    console.log('data', data)
  }).catch (err => {
    console.log('err', err)
  })
}

getProducts()

Для того, чтобы отлавливать ошибки с async await, нам нужно заворачивать весь блок кода в try catch.

const getProducts = async () => {
  try {
    console.log('data', await fetchProducts())
  } catch (err) {
    console.log('err', err)
  }
}

Ну и напоследок, давайте сравним код с промисами и с async await с небольшим callback hell.

const fetchProducts = () => Promise.resolve({data: [1,2,3]})
const fetchAdditional = (products) => Promise.resolve({data: [2,4,5]})

const getProducts = () => {
  return fetchProducts().then(products => {
    if (products.data.length) {
      return fetchAdditional(products.data)
        .then(additionalData => {
          return additionalData
        })
    } else {
      return products.data
    }
  })
}

getProducts().then(result => {
  console.log('result', result)
})

У нас есть 2 функции fetchProducts и fetchAdditional. В getProducts мы хотим, после получения продуктов, если массив не пустой, сфетчить дополнительные данные. Этот код уже начинает напоминать callback hell.

Давайте перепишем его на async/await.

const getProducts = async () => {
  const products = await fetchProducts()

  if (!products.data.length) {
    return products.data
  }

  return await fetchAdditional(products.data)
}

Я думаю теперь плюсы async await стали окончательно очевидны.

Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
sergey pavlov
5 лет назад
Большое спасибо за курс по ES6 !
monsterlessons
5 лет назад
На здоровье!
Илья Муромцев
6 лет назад
Благодарю за ценную информацию! =) ..и да, у тебя в футере на ссылке RSS выводит код страницы https://monsterlessons.com/api/rss ;-)
Aleksandr
6 лет назад
Огромное спасибо за курс, без него было бысовем тяжко воспринимать ES-6. Хочу спросить, а вот такой синтаксис это из ES-6? Если да то не могли бы вы сделать про это урок? Я имею в виду функцию со знаком вопроса и двоеточием. Это какое-то условие? Типа if/else ? return condition.apply(this, arguments) ? onTrue.apply(this, arguments) : onFalse.apply(this, arguments); Заранее благодарю.
monsterlessons
6 лет назад
На здоровье. То что вы написали, это тернарный оператор. По факту это if else в одну строку. if (a === 1) { one() } else { two() } a === 1 ? one() : two() Две эти конструкции равнозначны
Alexander Prylipko
6 лет назад
Приветствую! Реализация отличная + в разы сократил код. Но появилась новая проблема. Когда через Listener отслеживаю change в select у меня получается multiple requests. Получилось это предотвратить глобальной переменной (пример: let loading = false;) в которую я передаю true если запрос ушел на сервер и валидирую на входе в функцию. Но проблема в том функций таких хватает и получается что я засоряю сам контекст функции. Возможно есть какие-то умные решения, а то уже психовать начинаю =) Буду благодарен любой помощи =) Спасибо!
monsterlessons
6 лет назад
Добрый день. Я отвечаю только на комментарии относящиеся непосредственно к уроку, или близко к нему, и не даю консультаций к коду не связанному с уроками. Надеюсь на ваше понимание.
Вэл Грин
6 лет назад
Здравствуйте! Спасибо за видео) Есть вопрос. Не совсем понятно, что возвращается из функции. Я думала, возвращается результат, но оттуда возвращается промис, и потом соответственно вылетает ошибка. const fetchData = async () => { try { return await fetch('https://jsonplaceholder.typicode.com/posts'); } catch(err) { console.log(err); } } function logger(data){ console.log('data from logger',data); data.map(item => console.log(item.userId)); } logger(fetchData());
monsterlessons
6 лет назад
Добрый день. async await не содержит никакой магии и не несет нового функционала в языке. Это просто обертка вокруг промисов Поэтому async функция всегда просто возвращает промис. Вы можете использовать .then чтобы получить данные от промиса.
bloadvenro
6 лет назад
Здравствуйте! Спасибо за труд) Насколько мне известно, можно использовать await и с синхронными вызовами: let result = await syncFn(); При таком раскладе можно, к примеру, перебрать список функций смешанного характера (синхронного и асинхронного) и универсально отловить ошибки через try catch. Это может быть полезно, например, при валидации, где валидаторы могут быть одновременно асинхронными и синхронными.
monsterlessons
6 лет назад
Добрый день. На здоровье) Да можно, но я не сталкивался с таким кейсом в реальных проектах. Обычно валидаторы разделяют на синхронные и асинхронные (например redux-forms). В try catch можно завернуть любой код. Просто обычно, когда я вижу слово await, я подсознательно ожидаю, что внутри асинхронный код и использование его с синхронными функциями может его усложнить.
bloadvenro
6 лет назад
Валидаторы могут итерироваться с вызовом внутренним механизмом валидации, и там же содержимое брошенных ошибок собирается :) Сверху мы просто формируем очередь валидации каждого поля, только асинхронные проверки отодвигаем в конец)
monsterlessons
6 лет назад
Зависит от реализации. Вполне возможно реализовать так, как мы написали.
Антон Бурденюк
6 лет назад
Monster спасибо вам большое за эти видео уроки, никогда еще не писал коменты под видео, но ваша работа просто не может быть не откоментирована позитивным отзывом. Огромное спасибо )
monsterlessons
6 лет назад
На здоровье. Рад, что уроки полезные. Спасибо.
ZDima
6 лет назад
Хорошее видео, но хотелось бы уточнить некоторые вопросы: 1. promise и async await как я понял применяются только для асинхронного выполнения. Вопрос: асинхронным выполнение является только когда применяется setTimeout или есть еще что-то? т.е. без setTimeout это считается синхронным всегда? 2. Для решения практических задач возникает ли необходимость применения рекурсивного вызова setTimeout в пределах promise или async await? У меня почему-то не получилось (один раз выводит и все). 3. В каких случаях на практике удобно применять такое асинхронное поведение? можете ли привести пару примеров из практики (просто словами)?
monsterlessons
6 лет назад
Да, promise и async await нужно только для асинхронного выполнения. setTimeout, практически никогда не использующийся кейз асинхронного выполнения. Намного больше нас интересует взаимодействие с API. Когда мы хотим получить какие-то данные об бекенда, то это всегда происходит асинхронно. Соответственно Promise и async await решают эту проблему.
Zaibatsu International
6 лет назад
Спасибо, хорошее видео, еще бы упомянуть цепочку из await-ов как аналог цепочки then и вообще было бы неплохо
monsterlessons
6 лет назад
На здоровье. Вам не нужен аналог цепочки then, потому что весь код работает как синхронный и после получения данных вы можете делать с ними что угодно, как обычно.
Дмитрий Леонтьев
6 лет назад
Привет, так же предложение для коммерческого мейнстримного стека (я тоже первый в очереди за покупкой) : авторизация на React/Redux/Immutable JS + KOA (Express) + Node JS + MongoDB + Mongoose + Passport (JWT/OAuth) + BUILDERS (WEB PACK, GULP , BUBBLE) , реализация простого личного кабинета с возможностью расширения приложения
monsterlessons
6 лет назад
Привет. Спасибо за идею. Добавил в список.
evgeniy
6 лет назад
Спасибо! Шикарно объясняешь)) Запили, плиз, какое-нибудь приложение с микросервисной архитектурой в связке: Docker(Dokku) + GrapgQL + RethinkDB + NodeJS + (ReactJs or VueJs) + Gitlab ci/cd. Можно разбить видео на логические блоки, чтоб быстрее выпускать, каждый блок с отдельной стоимостью(профита будет больше). Я первый куплю:))
monsterlessons
6 лет назад
Спасибо за идею. Добавил в список будущих видео.
Алекс Бородулин
6 лет назад
Шикарное видео, спасибо)
monsterlessons
6 лет назад
На здоровье)