How To Master Async/Await With This Real World Example

How To Master Async/Await With This Real World Example

Along with writing this article, I have also created a YouTube video! 

Originally published by Adrian Hajdin  at freecodecamp.org

Table of Contents:

  1. Introduction (callbacks, promises, async/await)
  2. Real world example — Currency Converter that is receiving asynchronous data from two API’s.

Just a note…

Along with writing this article, I have also created a YouTube video! 

You can follow along and code while watching. I advise you to first read the article, and then code along with the video.

Link of the video: Learn Async/Await in This Real World Project

Introduction

Async/await is a new way to write asynchronous code. It is built on top of promises, therefore, it is also non blocking.


The big difference is that asynchronous code looks and behaves a little more like synchronous code. This is where all its power lies.

Previous options for asynchronous code were callbacks and promises.

Callbacks in action

setTimeout(() => {
  console.log('This runs after 1000 milliseconds.');
}, 1000);

Problem with callbacks — The infamous Callback Hell

Nesting callbacks within callbacks will soon start to look like this:

Callback Hell

The situation where callbacks are nested within other callbacks several levels deep, potentially making it difficult to understand and maintain the code.

Promises in action

const promiseFunction = new Promise((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 that function. The resolve function signals the Promise instance that it has finished.

Afterwards, we can call .then() and .catch() on that promise function: 

then — Runs a callback you pass to it when the promise has finished.

catch — Runs a callback you pass to it when something went wrong.

Async Functions

Async function provide us with a clean and concise syntax that enables us to write less code to accomplish the same outcome we would get with promises. Async is nothing more than syntactic sugar for promises.


Async functions are created by prepending the word async before the function declaration like this:

const asyncFunction = async () => {
  // Code
}

Asynchronous functions can be paused with awaitthe keyword that can only be used inside an async function. Await returns whatever the async function returns when it is done.

This is the difference between promises and async/await:

// Async/Await
const asyncGreeting = async () => 'Greetings';
// Promises
const promiseGreeting = () => new Promise(((resolve) => {
  resolve('Greetings');
}));
asyncGreeting().then(result => console.log(result));
promiseGreeting().then(result => console.log(result));


Async/Await looks similar to synchronous code, and synchronous code is much easier to understand.

Now that we’ve covered the basics, let’s move onto our real world example!

Currency Converter

Project clarification and setup

In this tutorial, we will build a simple but educational and useful application that is going to improve your overall knowledge of Async/Await.


The program will take in currency code we want to convert from and currency code we want to convert to, as well as the amount of money. Afterwards, the program will output the correct exchange rate based on the data from the APIs.

In this application we’re going receive data from two asynchronous sources:

  1. Currency Layer — https://currencylayer.com — You’ll need to sign up for free so you can use the API Access Key. This API will provide us with data needed to calculate exchange rate between currencies.
  2. Rest Countries — http://restcountries.eu/ — This API will give us information about where can we use the currency we just converted our money to.

For starters, create a new directory and run npm init, skip through all the steps, and install axios by typing npm i --save axios. Create a new file called currency-converter.js.

Firstly, require axios by typing: const axios = require(‘axios’);

Let’s dive into async/await

Our goal for this program is to have three functions. Not one, not two, but three asynchronous functions. The first function is going to fetch data about currencies. The second function if going to fetch data about countries. And the third function is going to gather that information into one single place and output it nicely to the user.


First function — Receiving Currency Data Asynchronously

We’ll create an asynchronous function that is going to take in two arguments, fromCurrency and toCurrency.


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

Now we need to fetch the data. With async/await, we can assign data directly to a variable; don’t forget to sign up and enter your own correct 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 under response.data.rates so we can put that into a variable just below response:

const rate = response.data.rates;

Since everything is being converted from the euro, below, we’ll create a variable called euro which will be equal to 1/currency we want to convert from:

const euro = 1 / rate[fromCurrency];

Finally, to get an exchange rate we can multiply euros by the currency we want to convert to:

const exchangeRate = euro * rate[toCurrency];

Finally, the function should look something like this:

Second function — Receiving Country Data Asynchronously

We’ll create an asynchronous function that is going to take currencyCode as an argument:


const getCountries = async (currencyCode) => {}

As we saw before, we are going to fetch data and assign it to a variable:

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

We’ll then map over the data and return country.name for each:

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

Finally, the function should look something like this:

Third and final function — Merging it all together

We’ll create an asynchronous function that is going to take fromCurrencytoCurrency, and amount as arguments:


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

First, we get the currency data:

const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);

Second, we get the countries data:

const countries = await getCountries(toCurrency);

Third, we save the converted amount to a variable:

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

Finally, we output it all to the user:

return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`;

All of that put together should look like this:

Adding try/catch to deal with error cases

We need to wrap all our logic in try, and catch the error if there is one:


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) {
    throw new Error(`Unable to get currency ${fromCurrency} and  ${toCurrency}`);
  }
};

Repeat the same for 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) {
    throw new Error(`Unable to get countries that use ${currencyCode}`);
  }
};

And since the third function is just working with what the first and the second function provided, there is no need for error checking there.

Finally, we can call the function and receive the data:

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

The output you’re going to receive:

That’s it!

You made it all the way until the end! If you get stuck along the way, feel free to check out the code on this repository. If you have any questions or feedback, let me know in the comments down below. Most helpful would be the support on YouTube since I have just created a channel! Click here, there is a lot of interesting stuff coming soon! :)


You can also check out the tutorial I did on Mongoose.


Originally published by Adrian Hajdin  at freecodecamp.org

===========================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Svelte.js - The Complete Guide

☞ The Complete JavaScript Course 2019: Build Real Projects!

☞ Become a JavaScript developer - Learn (React, Node,Angular)

☞ JavaScript: Understanding the Weird Parts

☞ JavaScript: Coding Challenges Bootcamp - 2019

☞ The Complete Node.js Developer Course (3rd Edition)

☞ Angular & NodeJS - The MEAN Stack Guide

☞ NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)

☞ Node.js Absolute Beginners Guide - Learn Node From Scratch





javascript

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

The essential JavaScript concepts that you should understand

The essential JavaScript concepts that you should understand - For successful developing and to pass a work interview

JavaScript Memory Management System

The main goal of this article is help to readers to understand that how memory management system performs in JavaScript. I will use a shorthand such as GC which means Garbage Collection. When the browsers use Javascript, they need any memory location to store objects, functions, and all other things. Let’s deep in dive that how things going to work in GC.

Grokking Call(), Apply() and Bind() Methods in JavaScript

In this article, we will have a look at the call(), apply() and bind() methods of JavaScript. Basically these 3 methods are used to control the invocation of the function.

JavaScript Tutorial: if-else Statement in JavaScript

This JavaScript tutorial is a step by step guide on JavaScript If Else Statements. Learn how to use If Else in javascript and also JavaScript If Else Statements. if-else Statement in JavaScript. JavaScript's conditional statements: if; if-else; nested-if; if-else-if. These statements allow you to control the flow of your program's execution based upon conditions known only during run time.

Top 15 Free JavaScript Frameworks for Web Applications

List of some useful JavaScript Frameworks and libraries for website, web apps, and mobile apps development, that developers should know about to make selection easier.