How to master the syntax async / await: a real example
- Transfer
This is a translation of the article by Adrian Hajdin, which was published on the freeCodeCamp website. Under the author, the author clearly and concisely explains the advantages of async / await, and shows how to use this syntax using a specific example.
Note ...
I not only wrote this article, but also created a video on YouTube!
You can follow the instructions in the video and program in the process of viewing. I advise you first to read the article and then write the code in the course of the video.
Video link: Learn Async / Await in This Real World Project
Async / await is a new way to write asynchronous code. This syntax is built on top of promises and therefore is not blocking.
The difference from other ways of creating asynchronous code is that in appearance and behavior, asynchronous code that is implemented via async / await resembles synchronous. And this is his advantage.
Previous ways to organize asynchronous code were callbacks and promises.
When you attach a callback function with each other code soon begins to look like this:
"Hell callbacks» (Callback Hell)
Hell callbacks
This is a situation in which the callbacks are invested in other callbacks in multiple levels, which is why it is difficult to understand code and manage it.
promiseFunction returns a promise that represents the process of this function. The resolve function makes the Promise object understand that the process is complete.
Then we can call .then () and .catch () for this function of promise:
then - starts the callback that you transmit when the promise is completed.
catch - triggers a callback that you send when something goes wrong.
The async functions provide us with a clean and concise syntax that allows us to write less code and get the same result as when using promises. Async is nothing but syntactic sugar for promis.
Async functions are created by adding the async keyword before declaring a function, for example:
Asynchronous functions can be suspended using await , a keyword that is used only within the async function . Await returns everything that the async function returns when it is executed.
The difference between promises and async / await:
Async / await is similar to synchronous code, which is much easier to understand.
Now that we have covered the basic principles, let's move on to a real use case!
Now we will build a simple, but useful (including for training) application that will improve your general knowledge of async / await .
The program will take the amount of money, the currency code from which we want to transfer this amount, and the currency code into which we want to transfer it. The program will then issue the correct exchange rate based on data from the API.
In this application, we are going to get data from two asynchronous sources:
First of all, create a new folder and run it
First, request axios by typing:
Our goal is for the program to have three functions. Not one and not two, namely three asynchronous functions . The first function will receive data on currencies, the second - about countries, and the third - to collect this information in one place and display it to the user in an orderly manner.
The first function is asynchronous receipt of currency data.
We will create an asynchronous function that will include two arguments - fromCurrency and toCurrency.
Now you need to get the data. Using async / await, you can assign data directly to a variable. Do not forget to register and enter your access key.
The data from the response is available in
Since everything is converted from euro, below we will create a variable called euro, which will be equal to 1 / of the currency from which we want to transfer money:
And to get the exchange rate, you need to multiply the euro by the currency in which we want to transfer money:
As a result, the function should look like this:
The second function - asynchronous data acquisition about the country.
We will create an asynchronous function that will use the currencyCode argument:
Like last time, we are going to get the data and assign it to a variable:
Then we establish a match in the data and return
As a result, the function should look something like this:
The third and last function - we merge everything together
We will create an asynchronous function that will include fromCurrency , toCurrency and the sum as arguments:
First we get the currency information:
Then the country data:
After that, save the converted amount to a variable:
As a result, we output all this to the user:
Collectively, it should look like this:
Adding a try / catch statement to handle errors
We need to wrap our logic with a try / catch block to catch errors, if any:
Do the same with the second function:
There is no need to check for a third function for errors, since it works with the data that the first and second functions provide to it.
As a result, we can call the function and get the data:
The result you get:
You have come all the way to the end! If something went wrong in the process, you can find the source code in this repository . If you have questions or want to leave a review, write a comment . For me, your support on YouTube would be the biggest help, because I recently created a channel there! Click here - soon there will be a lot of interesting things! :)
You can also watch the tutorial that I created on the Mongoose website .
Note ...
I not only wrote this article, but also created a video on YouTube!
You can follow the instructions in the video and program in the process of viewing. I advise you first to read the article and then write the code in the course of the video.
Video link: Learn Async / Await in This Real World Project
Introduction
Async / await is a new way to write asynchronous code. This syntax is built on top of promises and therefore is not blocking.
The difference from other ways of creating asynchronous code is that in appearance and behavior, asynchronous code that is implemented via async / await resembles synchronous. And this is his advantage.
Previous ways to organize asynchronous code were callbacks and promises.
Callback functions in action
setTimeout(() => {
console.log('This runs after 1000 milliseconds.');
}, 1000);
Callback functions problem - the notorious “callback hell”
When you attach a callback function with each other code soon begins to look like this:
"Hell callbacks» (Callback Hell)
Hell callbacks
This is a situation in which the callbacks are invested in other callbacks in multiple levels, which is why it is difficult to understand code and manage it.
Promises in action
const promiseFunction = newPromise((resolve, reject) => {
const add = (a, b) => a + b;
resolve(add(2, 2));
});
promiseFunction.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
promiseFunction returns a promise that represents the process of this function. The resolve function makes the Promise object understand that the process is complete.
Then we can call .then () and .catch () for this function of promise:
then - starts the callback that you transmit when the promise is completed.
catch - triggers a callback that you send when something goes wrong.
Async functions
The async functions provide us with a clean and concise syntax that allows us to write less code and get the same result as when using promises. Async is nothing but syntactic sugar for promis.
Async functions are created by adding the async keyword before declaring a function, for example:
const asyncFunction = async () => {
// Code
}
Asynchronous functions can be suspended using await , a keyword that is used only within the async function . Await returns everything that the async function returns when it is executed.
The difference between promises and async / await:
// Async/Awaitconst asyncGreeting = async () => 'Greetings';
// Promisesconst promiseGreeting = () =>newPromise(((resolve) => {
resolve('Greetings');
}));
asyncGreeting().then(result =>console.log(result));
promiseGreeting().then(result =>console.log(result));
Async / await is similar to synchronous code, which is much easier to understand.
Now that we have covered the basic principles, let's move on to a real use case!
Currency Converter
Clarification and customization of the project
Now we will build a simple, but useful (including for training) application that will improve your general knowledge of async / await .
The program will take the amount of money, the currency code from which we want to transfer this amount, and the currency code into which we want to transfer it. The program will then issue the correct exchange rate based on data from the API.
In this application, we are going to get data from two asynchronous sources:
- Currency Layer - https://currencylayer.com - you will need to register for free to use the API access key. He will provide us with the data necessary to calculate the exchange rate.
- Rest Countries - http://restcountries.eu/ - this API will provide information on where we can use the currency into which we just transferred our money.
First of all, create a new folder and run it
npm init
, skip all the steps and install axios by typing npm i -- save axios
. Create a new file called currency-converter.js
. First, request axios by typing:
const axios = require(‘axios’);
Let's dive into async / await
Our goal is for the program to have three functions. Not one and not two, namely three asynchronous functions . The first function will receive data on currencies, the second - about countries, and the third - to collect this information in one place and display it to the user in an orderly manner.
The first function is asynchronous receipt of currency data.
We will create an asynchronous function that will include two arguments - fromCurrency and toCurrency.
const getExchangeRate = async (fromCurrency, toCurrency) => {}
Now you need to get the data. Using async / await, you can assign data directly to a variable. Do not forget to register and enter your access key.
const getExchangeRate = async (fromCurrency, toCurrency) => {
const response = await axios.get('http://data.fixer.io/api/latest? access_key=[yourAccessKey]&format=1');
}
The data from the response is available in
response.data.rates
, so you can insert this expression into the variable just below the response:const rate = response.data.rates;
Since everything is converted from euro, below we will create a variable called euro, which will be equal to 1 / of the currency from which we want to transfer money:
const euro = 1 / rate[fromCurrency];
And to get the exchange rate, you need to multiply the euro by the currency in which we want to transfer money:
const exchangeRate = euro * rate[toCurrency];
As a result, the function should look like this:
The second function - asynchronous data acquisition about the country.
We will create an asynchronous function that will use the currencyCode argument:
const getCountries = async (currencyCode) => {}
Like last time, we are going to get the data and assign it to a variable:
const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
Then we establish a match in the data and return
country.name
for each currency code:return response.data.map(country => country.name);
As a result, the function should look something like this:
The third and last function - we merge everything together
We will create an asynchronous function that will include fromCurrency , toCurrency and the sum as arguments:
const convert = async (fromCurrency, toCurrency, amount) => {}
First we get the currency information:
const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);
Then the country data:
const countries = await getCountries(toCurrency);
After that, save the converted amount to a variable:
const convertedAmount = (amount * exchangeRate).toFixed(2);
As a result, we output all this to the user:
return`${amount}${fromCurrency} is worth ${convertedAmount}${toCurrency}. You can spend these in the following countries: ${countries}`;
Collectively, it should look like this:
Adding a try / catch statement to handle errors
We need to wrap our logic with a try / catch block to catch errors, if any:
const getExchangeRate = async (fromCurrency, toCurrency) => {
try {
const response = await axios.get('http://data.fixer.io/api/latest?access_key=f68b13604ac8e570a00f7d8fe7f25e1b&format=1');
const rate = response.data.rates;
const euro = 1 / rate[fromCurrency];
const exchangeRate = euro * rate[toCurrency];
return exchangeRate;
} catch (error) {
thrownewError(`Unable to get currency ${fromCurrency} and ${toCurrency}`);
}
};
Do the same with the second function:
const getCountries = async (currencyCode) => {
try {
const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
return response.data.map(country => country.name);
} catch (error) {
thrownewError(`Unable to get countries that use ${currencyCode}`);
}
};
There is no need to check for a third function for errors, since it works with the data that the first and second functions provide to it.
As a result, we can call the function and get the data:
convertCurrency('USD', 'HRK', 20)
.then((message) => {
console.log(message);
}).catch((error) => {
console.log(error.message);
});
The result you get:
That's all!
You have come all the way to the end! If something went wrong in the process, you can find the source code in this repository . If you have questions or want to leave a review, write a comment . For me, your support on YouTube would be the biggest help, because I recently created a channel there! Click here - soon there will be a lot of interesting things! :)
You can also watch the tutorial that I created on the Mongoose website .