in

JavaScript: Async Await

Javascript logo

Resources

Sample Promise

Async Await provides us with an easier way to work with Promises. To get started lets look at a couple of functions that use promises. Then we will work with them the typical Promises way, and then refactor that code into Async Await.

function makeRequest(location) {
    return new Promise((resolve, reject) => {
        console.log('Making Request to ' + location)
        if (location === 'Google') {
            resolve('Google says hi');
        } else {
            reject('We can only talk to Google');
        }
    })
}

function processRequest(response) {
    return new Promise((resolve, reject) => {
        console.log('Processing response');
        resolve('Extra Information: ' + response);
    })
}

makeRequest('Google').then(response => {
    console.log('Response Received');
    return processRequest(response);
}).then(processedResponse => {
    console.log(processedResponse);
}).catch(err => {
    console.log(err);
})

And if we run this in the console we get the following.

But if we change the request to anything else, like “Twitter”.

makeRequest('Twitter').then(response => {
    console.log('Response Received');
    return processRequest(response);
}).then(processedResponse => {
    console.log(processedResponse);
}).catch(err => {
    console.log(err);
})

Async Await

This is all to be expected so far based on what we know about promises. Now let us convert the makeRequest function into an Async Await function.

function makeRequest(location) {
    return new Promise((resolve, reject) => {
        console.log('Making Request to ' + location)
        if (location === 'Google') {
            resolve('Google says hi');
        } else {
            reject('We can only talk to Google');
        }
    })
}

function processRequest(response) {
    return new Promise((resolve, reject) => {
        console.log('Processing response');
        resolve('Extra Information: ' + response);
    })
}

async function doWork() {
    const response = await makeRequest('Google');
    console.log('Response Received');
    const processedResponse = await processRequest(response);
    console.log(processedResponse);
} 
doWork();

A couple of things right at the start:

  • We must wrap all of our Async items in a function, in this case doWork()
  • We must declare the function as an Async function
  • Setting the resolutions of the promises to variables is useful in case they are needed later as shown in the console.log of processedResponse
  • function must be called at the end to run (obviously)

Now the big difference between these two methods at this point is that the async function is lacking a way to handle errors which is what the .catch method was doing before. So currently with this new method if we try to request anything that isn’t Google we get the following:

Try/Catch Block

To solve this we can add error handling with a try/catch block.

async function doWork() {
    try {
        const response = await makeRequest('Google');
        console.log('Response Received');
        const processedResponse = await processRequest(response);
        console.log(processedResponse);
    } catch (err) {
        console.log(err)
    }
} 
doWork();

If at any point in the promises waterfall the promise is unfulfilled, it will immediately skip ahead to the catch and log the reject resolution of the promise.

Additional Example 1

The previous example is awaiting resolution of some type of API request promise. In this example from Frosty CMS we are working with a MongoDB (with Mongoose) and we are awaiting the deletion of data (then seeding new data for testing purposes).

async function seedDB(){
    try {
        await Comment.deleteMany({});
        await Blog.deleteMany({});
        for (const blogSeed of  blogSeeds) {
            let blog = await Blog.create(blogSeed);
            let comment = await Comment.create(
                                {
                                    author: "Duke Ellington",
                                    text: "This comment will be the same for every blog. But it's just seed data so who cares."
                                }
                            );
        blog.comments.push(comment);  
        blog.save();
        }
        } catch (err) {
            console.log(err);
        }
console.log("Blog Data Removed and Re-Seeded");        
}
Javascript logo

JavaScript: Promises 🤝🏽

Frosty CMS Logo

Frosty CMS: Display Comments ✏️