[Назад](./web_06.md) | [К содержанию](../readme.md#практика-1-введение-в-web-разработку) | [Дальше](./web_08.md) # Криптономикон-4 - Самостоятельная работа. Promise, async/await. ## #15 Криптономикон-4 - Самостоятельная работа (валидации). * [YouTube](https://www.youtube.com/watch?v=F7olyLbQeJo) * [RuTube](https://rutube.ru/video/ad58e437fbd7b1c072ee6c9634f2525c/) **Материалы к работе** * [Изменения в HTML](https://gitlab.com/vuejs-club/youtube-course/cryptonomicon-html/-/commit/85ac960b083c6138a3277164730f3a19b7b0dca3) * [Апи для загрузки списка монет](https://min-api.cryptocompare.com/data/all/coinlist?summary=true) * [Хуки жизненного цикла Vue](https://ru.vuejs.org/guide/essentials/lifecycle.html) ## Асинхронность в JS, Promise Асинхронное программирование — концепция программирования, при которой результат выполнения функции доступен спустя некоторое время в виде асинхронного (нарушающего стандартный порядок выполнения) вызова. Запуск длительных операций происходит без ожидания их завершения и не блокирует дальнейшее выполнение программы. В современном JS асинхронность реализуется через [Promise (ожидание)](https://learn.javascript.ru/promise) (раньше для этого использовались callback-функции). Итак, функция, которая не может вернуть результат сразу (например, знакомый уже вам **fetch**), возвращает специальный объект **Promise** (в русскоязычном инете его часто так и называют - "промис"). Когда результат будет получен, промис вызывает внутренние методы **fulfilled** при успешном завершении или **rejected** при ошибке (названия методов условные, они используются внутри промиса) Наружу у объекта "промис" выходит 3 метода: * **then** - при успешном выполнении "промиса" * **catch** - при ошибке * **finally** - при любом завершении работы В итоге вызов **fetch** может выглядеть примерно так: ```js fetch(url).then(res => { // здесь res строка, поэтому необходимо преобразовать ее в json-объект if (res.ok) { // метод json тоже асинхронный, поэтому мы возвращаем очередной промис return res.json() } else throw new Error('Что-то пошло не так') }).then(json => { return json }).catch(error => { // можем извлечь текст ошибки и показать клиенту }).finally(() => { // тут мы можем погасить какую-нибудь "крутилку", если запускали её перед fetch }) ``` В коде используется два метода **then**, это нормально и называется "цепочкой промисов". Используется, если промежуточный результат нужно преобразовать (у нас возвращается "промис" `res.json()`, но можно возвращать и синхронный результат). Выглядит достаточно грмоздко, поэтому придумали синтаксический сахар **async/await** ## [Async/await](https://learn.javascript.ru/async-await) Ключевое слово **await** перед вызовом функции говорит системе, что результат будет отложенным (функция вернёт "промис", а конструкция `await функция` вернет результат "промиса"). Чтобы система знала, что внутри функции используются **await** вызовы эта функция **должна** начинаться с ключевого слова **async**. Пока выполняется **await** функция выполнение вызывающего кода приостанавливается. ```js async parentFun () { await childFun() someFun() } ``` В примере выше вызов `await childFun` приостанавливает выполнение кода в функции `parentFun` (но не останавливает выполнение скрипта, в момент ожидания могут обрабатываться события) Например, в коде, который вы уже видели в прошлых заданиях, callback функция в методе **setInterval** объявлена асинхронной и внутри неё можно использовать **await**: ```js setInterval(async () => { const f = await fetch( `https://min-api.cryptocompare.com/data/price?fsym=${newTicker.name}&tsyms=USD&api_key=ce3fd966e7a1d10d65f907b20bf000552158fd3ed1bd614110baa0ac6cb57a7e` ) const data = await f.json() ... ``` >"Синтаксическим сахаром" называют код, который используют только при написании кода. Реальный JS-код преобразуется в "промисы" системой сборки (в одной из лекций мелькало слово "babel") К чему был весь этот бред? Чтобы вы понимали, что асинхронный код можно вызывать только в функции, объявленной как **async**. Т.е. не получится прямо в `