Elegant error-handling with ES7 async/await

Asynchronous is amazing

There is no denying that. If you're a full-stack or a back-end developer, you've probably learned Node.JS with callbacks. Callbacks were convenient. They allowed for asynchronous operations in a synchronous programming language, essentially making JavaScript fit for everything a back-end does. So naturally Node made a heavy use of them in its API.

And then, there was hell. Callback hell.

What do we do, then ?

Promises

ES6 brought the notion of Promise, or the representation of an asynchronous value. It might be available in 10 seconds, in 10 hours, or might well never be and fail. It allowed for elegant asynchronous code :

const someAmazingPromise = () => {
  return new Promise((resolve, reject) => {
    if (//doSomethingSuccessful) {
      resolve(someDataHere);
    } 
    else {
      reject(someDataHere);
    }
});

Which you could then use this way :

  someAmazingPromise()
    .then(data => {return doSomethingWith(data)})
    .then(parsedData => {return doSomethingElsewith(parsedData)})
    .catch(someMeaningfulFailMsg => doSomethingWithThrow(someMeaningfulFailMsg));

Yes, chaining promises felt really amazing to write and is pleasing to the eyes. And then came..

async/await

ES7 brought async/await, or writing asynchronous code as if it was synchronous. Our code would look like this now :

  // Note the main function, as await can only be used within async functions, so it cannot be used at the top level of your module, except if you have a main function. Ah, reminds me of good ol' C programming ! 
  const main = async () => {
    try {
      const data = await someAmazingPromise();
      const parsedData = await doSomethingWith(data);
	  doSomethingElsewith(parsedData);
    } catch(e) {
      doSomethingWithThrow(e);
    }
  }

Amazing, isn't it ? Unfortunately, many people, me included, think that using try/catch blocks ruins the whole readability of the async/await syntax. But did you know you could chain a catch method to your await ? For example

  const data = await someAmazingPromise()
    .catch(someMeaningfulFailMsg => doSomethingWithThrw(someMeaningfulFailMsg));

What is this, dark magic ? Nope, just JavaScript being JavaScript. When you use await, what you're basically doing is going into the .then() method of your Promise. But the catch method also is available, and is perfectly chainable. Many people don't know this, as they imagine async/await is something really magical, when in reality it's just syntactic sugar for Promises.

As such, I highly advise everyone to catch errors this way. Of course, this won't fit every scenario and is less flexible/powerful than a try/catch block, but I like to use it whenever possible for readability !