Async & Await
Tags: javascript, es6, asynchronous, promises
Published: 2020-05-24 22:20:02

For most of the new ES6 features I was happy to adapt. It felt fun and cool to be on the hip side of things with my one-liner arrow functions and chic de-structuring. However... as cool as I once was, I met my match when ES8 came along. As soon as I ran into the async/await keywords I just turned around and went home.

I suppose my reasoning was no different than anyone else's when they resist change or refuse to modify an old habit. I mean really, things were going so well with promises and I was totally content with my .then() and .catch() architecture. So, I decided I would just say it like it is and tell ES8, "Thanks, I really appreciate the offer... but I'll pass on async/await. Good riddance!"

Annoyingly, not everyone seemed to follow my lead. I only continued to realize this as I would see these two keywords come up more and more in other developers code. Eventually, I buckled. I had to. The pain of the same was now bigger than the pain of the change.

So what did I do about it? The same thing I always do when I need to confront a monster in my life... I grabbed my sword, shield, and helmet went after that monster like there was no tomorrow! Put another way: I built a concise mobile application to better understand and demonstrate async/await's functionality, and now I get to share that with you. Hope you enjoy!

To get started on our journey I'll begin with some of the commands I ran to get my app up and running and then I'll walk through the code that demonstrates this great asynchronous functionality.

First, let's create our mobile applications (this is by no means specific to only mobile applications, that is just what I've had a large interest in creating as of recent). I installed Expo globally and then used it to initialize my React-Native application, similar instructions can be found in their [documentation](https://docs.expo.io/). I also installed Axios for an API request.
```
$ npm install --global expo-cli
$ expo init my-project
$ expo install axios
```
Once everything is installed we can change App.js to App.jsx and include the component we are about to create, AsyncAwait, as well as some simple styling for a full screen view:
```javascript
import React from 'react';
import { StyleSheet, SafeAreaView } from 'react-native';

import AsyncAwait from './app/AsyncAwait';

export default function App() {
  return (
    <SafeAreaView style={styles.container}>
      <AsyncAwait />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

```
Now let's work on actually building out our AsyncAwait component. In our project folder we can create a folder named "app" and store our AsyncAwait.jsx inside of it. Next we'll use set up a react native functional component with basic boilerplate code which will include the useState hook, a few react native components, and axios.
```javascript
import React, { useState } from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import axios from 'axios';

const AsyncAwait = () => {
  return (
    <View>
      <Text>This is our AsyncAwait Component</Text>
    </View>
  )
}

export default AsyncAwait

const styles = StyleSheet.create({})
```
And just like that we're able to see this component render on our iOS Simulator! Let's keep it up and get to some functionality. Here we'll add in two pieces of state and build our aysnc/await function:
```javascript
// useState hooks
  const [imgSource, setImgSource] = useState(null);
  const [loading, setLoading] = useState(false);

  const showAvatar = async () => {
    // Show loading text
    setLoading(true);
    console.log('Loading...');

    // Request github avatar
    const githubResponse = await axios.get('https://api.github.com/users/jameseaster');
    const githubUser = await githubResponse.data;

    // Pause here for 2 seconds
    await new Promise((resolve, reject) => setTimeout(resolve, 2000));

    // Remove the loading text
    setLoading(false);
    console.log('Image Added!');

    // Show the avatar
    setImgSource(githubUser.avatar_url);

    // Wait another 2 seconds
    await new Promise((resolve, reject) => setTimeout(resolve, 2000));

    // Remove the avatar
    setImgSource(null);
    console.log('Reset');
```

This being the meat and potatoes of our async/await exploration makes it feel only necessary to go line by line and describe what's happening in our function.

To begin we absolutely must include the async keyword in our function declaration. This does two things: 
1. Allows us to use the await keyword
2. Allows our function to return a promise.

Next we set the value of loading to true and log "Loading..." to the console. The loading variable in state will affect our conditional which we'll add next.

We have now arrived at our first await keyword. This little guy will wait for the result of our axios request to github. If the request is a success he will return the results, if the request fails he will throw an error. (You can also explore handling these results with try/catch blocks!)

Again we await for the response from github to assign the githubResponse.data to githubUser. Next we pause, literally just pause for two seconds while await waits on setTimeout. This is to help show how await will wait for the result of a function. This also helps pretend like github took that long to send us a response to our GET request (teehee). We remove the loading text and show the image of the github user (me, in this case) we queried for.

Finally, after pausing to look at my avatar for two whole seconds, we clear our state to set up our app to do it all over again.

To see this in action we'll simply reconstruct our return statement with these three conditionally rendering statements and a modest amount of styling.
```javascript
// return statement
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      // Renders Async/Await button if imgSource and loading are false
      {!imgSource && !loading ? <Button title="Async/Await" onPress={showAvatar} /> : null}
      // Will render "Loading" loading is true
      {loading ? <Text style={styles.text}>Loading...</Text> : null}
      // Will render our image if imgSource is true and loading is false
      {imgSource && !loading ? <Image style={styles.img} source={{ uri: imgSource }} /> : null}
    </View>
  );
};

export default AsyncAwait;

const styles = StyleSheet.create({
  text: {
    fontSize: 20,
  },
  img: {
    width: 250,
    height: 250,
  },
});
```
That'll do it! I hope this code, pseudocode, and concise mobile application have been helpful in introducing you to async/await and provided you with a simple template to explore even more functionality. As you continue to build out your own applications with this awesome feature your code will certainly grow flexible and dynamic. Don't (a)wait!