Понимаем Async/Await на примере Конвертера Валют

Vlad Kopenkin
Jan 19 · 5 min read
ES7 — Async/Await

Содержание:

  1. Вступление (колбэки, промисы, async/await)
  2. Реальный пример— Конвертер Валют, обрабатывающий асинхронные данные из двух API.

На заметку…

Вместе со статьей, автор записал и YouTube видео [ENG]!

Вступление

Async/await - это новый способ написания асинхронного кода в JS. Он построен поверх промисов, поэтому не блокирует параллельные операции.

Ранее вариантами написания асинхронного кода были: колбэки и промисы.

Колбэки в действии

setTimeout(() => {
console.log('Это сообщение отобразится через 1000 миллисекунд.');
}, 1000);

Проблемы колбэков — Ад колбэков

Вкладывая колбэки внутри колбэков в скором времени мы получим что-то подобное:

Ад колбэков

Ад колбэков

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

Промисы в действии

const promiseFunction = new Promise((resolve, reject) => {
const add = (a, b) => a + b;

promiseFunction возвращает Промис, который представляет процесс этой функции. Функция resolve оповещает сущность Промиса о завершении работы.

Впоследствии, мы можем вызвать .then() и .catch() относительно функции промиса:
then — Запускает колбэк, который вы ей(then) передаете, когда промис закончит работу.
catch — Runs a callback you pass to it when something went wrong.

Асинхронные функции

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

Чтобы создать асинхронную функцию нужно добавить слово async перед объявлением функции:

const asyncFunction = async () => {
// Код
}

Работу асинхронных функций можно приостановить с помощью await, ключевое слово используемое только внутри асинхронных функций. Await вернет значение возвращаемое асинхронной функцией после окончания её работы.

Отличие между промисами и async/await:

// Async/Await
const asyncGreeting = async () => 'Привет';

Конструкция Async/Await похожа на синхронный код, который куда легче для восприятия.

Итак, мы прошли основы, пора погрузиться в пример из реального мира!

Конвертер Валют

В этом руководстве мы создадим простое, но полезное приложение, которое поможет нам разобраться в Async/Await.

Приложение принимает три аргумента: код валюты, которую пользователь хочет ковертировать и код валюты, в которую пользователь хочет конвертировать, также колличество денежных единиц. После чего приложение выведет результат конвертации базируясь на данных из API.

В этом приложении мы будем запрашивать данные из двух асинхронных ресурсов:

  1. Currency Layer https://currencylayer.com — Вам нужно зарегистрироваться, чтобы использовать ключ доступа к API. API предоставит нам данные для вычисления курса обмена между валютами.
  2. Rest Countrieshttp://restcountries.eu/ — API предоставит нам информацию о том, в каких странах используется конвертируемая нами валюта.

Для начала создайте новую папку и запустите команду npm init, можете смело пропускать все шаги through all the steps. Установите axios выполнив npm i --save axios.Создайте новый файл currency-converter.js.

Первым делом объявите axios в начале файла:
const axios = require(‘axios’);

Погружаемся в async/await

Определим цель: создать три функции. Не одну, не две, а три асинхронных функции. Первая будет запрашивать данные о валютах. Вторая функция запросит данные о странах. Третья обработает эту информацию и выдаст ее в привычном для пользователя виде.

Первая функция —Асинхронное получение данных о Валюте

Мы создадим асинхронную функцию, которая принимает два аргумента: fromCurrency and toCurrency.
fromCurrency — код конвертируемой валюты.
toCurrency — код валюты в которую конвертируем.

const getExchangeRate = async (fromCurrency, toCurrency) => {}

Теперь нам предстоит запросить данные. С помощью async/await, мы можем определить данные сразу в переменную; не забудьте зарегистрироваться и ввести свой ключ доступа.

const getExchangeRate = async (fromCurrency, toCurrency) => {
const response = await axios.get('http://data.fixer.io/api/latest? access_key=[ВАШ_КЛЮЧ_ДОСТУПА]&format=1');
}

Данные из ответа (response) доступны по следующему пути:response.data.rates. Определим их в переменную под ответом:

const rate = response.data.rates;

Так как мы конвертируем в Евро, ниже, создадим переменную под названием euro и зададим ей значение — 1/валюта, которую мы конвертируем:

const euro = 1 / rate[fromCurrency];

Наконец, чтобы получить курс обмена нам нужно умножить евро в валюту которую мы хотим конвертировать:

const exchangeRate = euro * rate[toCurrency];

Функция должна выглядеть примерно так:

Вторая функция— Асинхронное получение данных о стране

Создадим асинхронную функцию, которая принимает аргумент currencyCode(код валюты):

const getCountries = async (currencyCode) => {}

Как и раньше, мы запрашиваем данные и определяем их в переменную:

const response = await axios.get(
`https://restcountries.eu/rest/v2/currency/${currencyCode}`
);

Перебираем массив данных и возвращаем country.name для каждого элемента:

return response.data.map(country => country.name);

Конечный вариант функции:

Третья и последняя функция — Соединяем данные вместе

Создадим асинхронную функцию принимающую 3 аргумента: fromCurrency, toCurrency, amount.

const convert = async (fromCurrency, toCurrency, amount) => {}

Запрашиваем данные о Валютах:

const exchangeRate = await getExchangeRate(
fromCurrency,
toCurrency
);

Запрашиваем данные о странах:

const countries = await getCountries(toCurrency);

Сохраняем конвертированные данные в переменную:

const convertedAmount = (amount * exchangeRate).toFixed(2);

Выводим результат для пользователя:

return `${amount} ${fromCurrency} стоит ${convertedAmount} ${toCurrency}. Вы можете потратить валюту в приведённых странах странах: ${countries}`;

Вы должны получить что-то подобное:

Добавляем try/catch для отлова ошибок

Нам нужно обернуть логику приложения в try, и “поймать”(catch) ошибку, если такова будет:

const getExchangeRate = async (fromCurrency, toCurrency) => {
try {
const response = await axios.get('http://data.fixer.io/api/latest?access_key=f68b13604ac8e570a00f7d8fe7f25e1b&format=1');

Повторим тоже самое для второй функции:

const getCountries = async (currencyCode) => {
try {
const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);

Так как третья функция использует данные передаваемые первой и второй функцией — нет нужды проверять на ошибки третью функцию.

Наконец, мы можем вызвать функцию и получить данные:

convertCurrency('USD', 'HRK', 20)
.then((message) => {
console.log(message);
}).catch((error) => {
console.log(error.message);
});

Вы получите примерно такой ответ:

Оригинал статьи — ссылка

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade