How to use ES8’s Async (and Await) to write concise promise-returning functions

It’s no secret (nor surprise) that async/await is one of the most anticipated features of ES8/ES2017. While there are lot of great resources already about the magic of the await keyword, its unsung sidekick async hasn’t gotten the same attention.

If you’ve used async/await before, you know that async is what allows await to work and is required in the nearest-parent function declaration of any use of the await keyword. Without async, await would just block code execution. That would negate JS’s asynchronous nature, one of JS’s best features and the reason JS can be used server-side (e.g. in Node). In order to do this, async makes the function, well, asynchronous by making the function return a promise, allowing other code to continue running while it awaits.

The side-effect of this is that async makes writing promised-based asynchronous functions both simple and synchronous-like:

  1. The promise returned by an async function resolves using .then() — just like any other promise — when the function returns, with the value that is returned — just like a synchronous function
  2. The promise returned by an async function catches an error using .catch() when the function throws an error

Let’s say we have a function that returns a promise that resolves after it gets some data from an API. Using promises, this might look like the following:

const withPromise = () => {
 return new Promise((resolve, reject) => {
   request(‘https://google.com')
   .then((data) => {
     // Pass data to promise resolution
     resolve(data);
   })
   .catch((err) => {
     // Reject with error
     reject(err);
   });
 });
}

Which requires instantiating a new Promise object, then calling .then, .catch, resolve and reject function. Promises require a lot of baggage to get them to work, not to mention a whole set of vocabulary unique to them.

Using async, we can achieve the same in a few lines

const withAsync = async () => {
 try { return await request(‘https://google.com') }
 catch (err) { throw err }
}

Which not only is concise and reads just like synchronous code, but will return a promise just like the first snippet.

withPromise().then(data => console.log(data));
withAsync().then(data => console.log(data));

(The above snippets use request-promise, a module to make http requests that return promises. They’re also trivial functions that just wrap around the the request method. Also on Medium.)

Written on August 2, 2017