Callbacks VS Promises VS Async/Await

While scrolling through the announced speakers for this weeks BerlinJS meetup I noticed Mohamed Oun will be giving his first ever talk (good luck by the way) on the JS worlds latest big hit, Async and await. So I thought I might as well do my own summary so I can compare notes ;)

Now by no means am I going to tread new ground with this blog but at least for me this whole promise & async/await thing didn’t make sense until I actually used it. And that’s what we’ll do.

To those coming from other languages, the benefit promises and async+await provide is a clean and readable way to chain functions, and implement reliable and concise flow control. Nothing more, nothing less.

Whether you take walk, cycle, or take a bus, you can still get where you want to go. Same for function callbacks VS Promises.

Let’s do this → The Setup

Let’s imagine we’ve got a node.js application, which is able to posting data from a form, to a controller, which via mongoose(including a bit of middleware) is storing in our DB.

This scenario gives us a couple of options, well three:

Callbacks

The TLDR of this is basically that if you have multiple function that need to execute within our controller, JS, due to it’s async nature won’t wait for a function to complete execution before moving onto the next. How people started getting around this is by using callbacks as you can see below.

We call functionA, and the execution of any subsequent functions become reliant on the return of functionA.

Now the problem with this starts appearing when we have more complex functions. Perhaps you need to sanitise your data, or run validations, or build associations with other records in the DB. You quickly arrive arrive at what many refer to as callback hell.

We start having to nest callbacks and things quickly become difficult to read.

Already a tiny Christmas tree starts to take shape.

Promises

A Promise is an object representing the eventual completion or failure of an asynchronous operation.

We can avoid that nested, difficult to read mess and achieve the same goal using something like this.

Let’s say we want to find another record and build an association before saving, we know what that might look like in the world of callbacks, but with promises we end up with a chain somewhat similar to this:

Promises allow us to cleanly chain chain subsequent operations while avoiding callback hell and as long as you always return a promise for each of your then blocks, it will continue down the chain.

Async/Await

Now the cool thing here as long as my function is declared as async, simply adding await to a call, will do the exact same thing as any of the above es6 promise based solutions, but with even cleaner markup.

async…await…await

It’s elegant and simple, but the only trade-off in my opinion is how to handle errors. Regular promises provide us with a nice and easy catch block that simplifies dealing with exceptions and errors, while async functions really don’t have a nice way to catch errors to my knowledge. So you need to do something like this.

try…catch…everywhere?

Now it’s not pretty, but for the sake of my little example please indulge me. And of course there are plenty of tricks and strategies for dealing with this in the real world you.

And there you have it

An application of promises and async/await in a day to day use case that almost every developer out there is familiar with. Thanks for taking the time to read it.

Did you spot an error? Am I talking nonsense?

Let me know if you think I’ve got the wrong end of the stick! I’m human, I make mistakes, I’m happy to learn from ’em :)

Sources:

I’m in the process of watching Wes Bos’s talk on Async + Await and I cannot recommend it highly enough if you want to know more (he describes error handling in so much more detail, seriously it’s great). Actually I’d recommend just following him in general (I’m a huge fan Wes Bos!).

MDN web docs on using Promises

MDB web docs on async + await