paint-brush
Async / Await Warm Upby@captaindaylight
2,088 reads
2,088 reads

Async / Await Warm Up

by paul christopheNovember 17th, 2016
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

If you’re used to using Promises, <a href="https://hackernoon.com/tagged/async" target="_blank"><em>async</em></a><em> / await </em>is an elegant way to make your <a href="https://hackernoon.com/tagged/javascript" target="_blank">javascript</a> more legible. It evaluates as synchronous code but returns a promise that executes on the next <a href="https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/" target="_blank">microtask</a>.

Company Mentioned

Mention Thumbnail
featured image - Async / Await Warm Up
paul christophe HackerNoon profile picture

If you’re used to using Promises, async / await is an elegant way to make your javascript more legible. It evaluates as synchronous code but returns a promise that executes on the next microtask.

Let’s jump right in and poke around. Open up the babel repl and code along with me. Take a simple function and add async to the beginning:



async function sayHello() {return 'hello';}

console.log(sayHello()); // => Promise {}

You’ll see that calling this function returns a Promise rather than “hello”. This is because anything returned from an async function is automatically wrapped in a promise. In order to log “hello” we could do this:


sayHello().then(str => console.log(str)) // => 'hello'

OK so what about await?

First, write a function that returns a promise:







function mapLater(arr, fn, time) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(arr.map(fn));}, time);});}

Pretty straight forward, we map over an array after given amount of time. Now let’s use that in an async function.



**async function addAndMultiply(arr) {const added = await mapLater(arr, i => i + 2, 2000);const multiplied = await mapLater(added, i => i * 2, 2000);


console.log(multiplied);}**

addAndMultiply([1, 3, 6, 20]); console.log('hello')

// => 'hello'// 4 secs later => [6, 10, 16, 44]

You’ll see that “hello” is logged before we are returned our array. Our async function is non-blocking.

It’s important to note that await must always be inside of an async closure. Calling it in the global scope or in a function without the the async keyword will throw an error.

Handling errors

Imagine something goes wrong with our original mapLater function:




...setTimeout(() => {reject('nope');}, time);

Currently, we have no way of surfacing the error in our async addAndMultiply function. When we run it, the function will fail silently. To handle errors, one solution is to use try / catch:






async function addAndMultiply(arr) {try { const added = await mapLater(arr, i => i + 2, 2000);const multiplied = await mapLater(added, i => i * 2, 2000);console.log(multiplied);} catch(err) { console.error(err); // 2 secs later => 'nope'}}

Since errors bubble up by default, another practical solution would be to handle errors at the async entry point:

intricatelyNestedAsyncFunc().catch(err => console.error(err));

Real World

Use it today! So many great libraries provide APIs that return promises. For example, if you’re using fetch to retrieve data, you can start doing things like:








async function getProfileData(id) {try {const users = await getUser(id);...} catch {...}}

To use async / await now you’ll need to use Babel’s transform-async-to-generator.