Batman and Promises
Tags: javascript, promises, asyncawait
Published: 2019-01-29 16:44:29

---
title: Batman and Promises
published: true
description: A Quick Discussion on JavaScript Promises
tags: javascript, promises, async/await
---

# Alfred

Imagine you're the CEO of some business.  Wayne Enterprises I suppose.  Here you are putzing around in the Batcave trying to figure out what the Joker's going to do next, but you, Mr. Wayne, have a hankering for some caffeine.  So you fetch Alfred and tell him, "get me a coffee."

So Alfred goes to get you a coffee.  While he's out and about, you're still free to continue polishing the Batmobile and searching for information on the Joker on the Batcomputer and fixing the holes and tears in your Bat armor.

After a little while, Alfred returns.

Promises are Alfred.  A Promise is a task JavaScript performs with an assurance that it will, at some point, return with some value.  It might not be the value you want, but it will be some sort of value.  Promises are asynchronous.  Actions passed to a Promise are put on the event loop rather than the function stack, which allows the other functions in your code to continue executing while you await your promise.

Here's a basic Promise:

```javascript
new Promise((resolve, reject) => {
    doTheThing((error, value)=> {
        if(error) {
            reject(new Error('something broke'));
        } else {
            resolve(value);
        }
    });
});
```

We have some function, `doTheThing()` that gets some value.  What it is doesn't really matter.  Maybe it's an API call or something.  Either way, the basics work like this.  If you get the value you want, you pass it to the `resolve()` function.  If you don't get the value you want, you call `reject()` and pass it an error or some other value you'd want if the Promise returns an error.

Any object passed to resolve, is then passed to the callback function of any `then()` call.  `then()` is fired immediately after `resolve()` and will perform the action you desire to have happen once your Promise is resolved.  `catch()` works with `reject()`.  `catch()` also takes a callback and the value passed into `reject()` is then passed into the callback `catch()` uses.  If you have multiple promises and multiple `then()` methods chained onto it, `catch()` is a one stop shop for all errors that are thrown; you only ever need one `catch()`.

So to rewrite this in terms of our Alfred example:

```javascript
const coffee = new Promise((resolve, reject) => {
    getCoffee((error, coffee)=> {
        if(error) {
            reject(new Error('no coffee!');
        } else {
            resolve(coffee);
        }
    });
});
coffee.then((coffee) => drink(coffee))
    .catch((error) => console.error(error.msg));
```

Alfred comes back and says he has your favorite coffee!  Your Promise is resolved and you can drink the coffee.  Alfred comes back and tells you he failed to get coffee because the Joker blew up all the coffee shops.  Your Promise has been rejected.  You get mad, suit up and head out in the batmobile to handle this . . . error.

# Sandwiches

After handling the Joker, you are hungry.  You want a sandwich!  But not just any sandwich.  The Batman has a sophisticated taste after all.  So you tell Alfred, that you want cheese from a specialty cheese shop, meat from your favorite deli, and fresh bread from your favorite baker.

Alfred now has to handle three promises at once.

This is where `Promise.all()` comes in.  `Promise.all()` handles an array of promises and will not resolve until _all_ the promises in the array are resolved.  If any one of them are rejected, they are _all_ rejected.

```javascript
const sammich = Promise.all([getBread, getCheese, getMeat]);
sammich
    .then((nom) => eat(nom))
    .catch((error) => console.error(error.msg));
```

When Alfred returns, you either have all three parts to your sandwich, or you don't have a sandwich.

But why get the individual ingredients one at a time when there are so many delicious Gotham City sandwich shops to choose from?  You decide you want a sandwich, but you can't decide between three different stores, so you'll just eat the first sandwich that is returned from you.  You send Alfred, Robin, and Gordon out separately to get you a sandwich.

This is `Promise.race()`.  `Promise.race()` takes an array of Promises and returns the first one to be resolved, skipping any that get rejected.  Only if all of them are rejected, will `Promise.race()` be rejected.

```javascript
const sammich = Promise.race([sandwich1, sandwich2, sandwich3]);
sammich
    .then((nom) => eat(nom))
    .catch((error) => console.error(error.msg));
```

Robin came back first, so you eat his sandwich.

# Async/Await

But here's the thing, using `.then` and `.catch` get clunky.  Can we get around this?  You are after all, _The Batman_ and your batcave could use a little cleaning up.

Async/Await offers some clean up.  It allows for your flow control in your code to feel more natural.  The way it works is simple, but it only works on Promise objects.  If you mark a function as `async` and mark a line inside that function with `await`, execution of that function will halt on that line while waiting for that promise to be resolved or rejected.  Meanwhile, all the other functions will keep executing.  The execution of the async function is thrown into the event loop and will only be executed once a value is returned and the function stack is cleared.

While Alfred, Gordon and Robin are going about getting your sandwiches, you're free to tinker about the batcave and do whatever you want while you wait, so long as what you want to do doesn't require those sandwiches.

`await` is exactly what it sounds like, the execution _must_ `await` the resolution or rejection of this promise.  Any rejection is picked up by the `catch` block of a try/catch.

```javascript
async function waitForCoffee() {
    let coffee;
    try {
        coffee = await getCoffee();
        coffee.drink();
    } catch(error) {
        console.error(error.msg);
    } finally {
        thank('Alfred').forServices();
    }
}
```
> We're assuming `getCoffee()` returns a Promise in this example.

Here you have a more top to bottom flow of control with async/await.  There's no other benefit to using async/await over `.then()/.catch()`, it isn't faster or necessarily more performant.  It's just easier to read and manage.

Just be aware that async/await only works on Promises.  If you try using it on something like the geolocation API, it won't work, unless you wrap those functions in Promises first.

That is Promises in a nutshell.