Intro to JavaScript Promises
Tags: javascript, beginners
Published: 2020-04-27 00:50:57

### Async Actions

If you have written JavaScript before, you are most likely aware of asynchronous programming. Since JavaScript can only perform one command at a time (it is a single-threaded language), operations that are long, such as retrieving data from a server, can block the main thread. This is bad because to the user, your program may appear unresponsive.

An example of this would be making a fetch request to an API and waiting for the response. While waiting for the response from the API, we want our program to be able to execute other processes. Asynchronous programming allows JavaScript to continue execution of other processes while waiting for another process to resolve. Here is a good [blog](https://codesthq.com/asynchronous-and-single-threaded-javascript-meet-the-event-loop/) that goes more in depth on asynchronous JavaScript and the event loop.

### Promises

A [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) is a JavaScript object that, "represents the eventual completion (or failure) of an asynchronous operation, and its resulting value." Promises were first introduced to JavaScript in ES6. With this new feature, functions can return a promise and continue executing other processes while waiting for it to resolve or settle. Once the promise is resolved, the program can continue with the use of that data it was waiting on.

Before promises were introduced, callbacks and events were used for asynchronous programming, but this presented some challenges. Some people have referred to this as callback hell, as the code can be extremely hard to understand. Here is an example from this Stranger Things themed [blog post](https://dev.to/amberjones/how-to-escape-callback-hell-with-javascipt-promises-42d0):

```
fightTheDemogorgon(function(result) {
  rollForDamage(result, function(seasonsLeft) {
    closeTheGate(seasonsLeft, function(finalResult) {
      console.log('Hawkins is safe for ' + finalResult + ' more seasons.');
    }, failureCallback);
  }, failureCallback);
}, failureCallback);
```

![This is fine](https://media.giphy.com/media/NTur7XlVDUdqM/giphy.gif)

#### A Metaphor

I like to think of promises like a ticket you would get from a food truck after you order. The ticket has a number, so it can be associated with your order and you can perform other actions while you are waiting for your food. Meanwhile, the food truck is hard at work getting the order they "promised" ready for you.

![Food truck GIF](https://media.giphy.com/media/d31vot4Yoy9r8dwY/giphy.gif)

##### States

Promises have three possible states: fulfilled, rejected, and pending.

The initial state of the promise is pending. This is when you first get the ticket from the food truck and are waiting for your order. Maybe during this time you are doing another action you need to complete, like calling your mom. We all know we need to do that more.

A promise is fulfilled if the operation was completed successfully. This would be when the food truck has successfully given you your food. A promise is rejected if it failed. If rejected, there will be an error associated with the promise. This would be the case if the food truck ran out of an ingredient and couldn't make your order. Maybe the error would be a message from the employee telling you what went wrong.

#### Then / Catch Methods

Two methods that are frequently used with promises are `.then()` and `.catch()`. These methods will execute when a promise is "settled," meaning it is no longer pending. Both `.then()` and `.catch()` return promises themselves and can be chained onto the original async function.

##### Then

The `.then()` [method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) takes up to two arguments. The arguments should be callback functions to execute when the previous async action settled. The first callback will execute in the case of the promise being **fulfilled** and the second will execute in the case of the promise being **rejected**. These callback functions are named `onFulfilled()` and `onRejected()` in the MDN documentation, but most programmers use arrow functions for their callbacks like so:

```
return fetch(`${baseUrl}/api/v1/concert/${concertId}/users`, configurationObject)
      .then(r => r.json())
      .then(users => {
        if (users.error) {
          alert(users.error)
        } else {
          dispatch(setUsersOfConcert(users.data))
        }
      })
      .catch(error => console.log(error))
```
The `onFulfilled()` function takes one argument, the fulfillment value. In this case, I called the value `r` for response. The `onRejected()` callback takes one argument, the reason for the rejection. In this case, I didn't use the second argument for `.then()`, but this was handled with `.catch()`, which you will read about below. The promise returned by `.then()` will resolve to the return value of the passed in callback, or to its originally settled value if the passed in argument was not a callback function. For example, if `.then(console.log("hi"))` was chained onto an async function, the promise will resolve to undefined.

As you can see, I chained the `.then()` method on with one argument, to execute in the case of the promise being fulfilled. In this case, I take the response body from the API and parse it to json. The `.json()` method returns a promise as well, hence the additional `.then()` chaining.

##### Catch

The `.catch()` [method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) is basically the same as `.then()`, however it deals with the case of the promise being rejected.  From the docs, this method actually calls `.then()` under the hood, with the first argument as `undefined`. As mentioned earlier, `.catch()` returns a promise as well. From the docs, this promise is resolved unless the `onRejected()` callback function returns an error, or returns a promise that is rejected. The promise returned by `.catch()` will resolve to the return value of the passed in callback.

[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) has a pretty good diagram to explain the flow of chaining:

![MDN Promises](https://mdn.mozillademos.org/files/15911/promises.png)

In most cases that I have seen, developers use `.catch()` to log errors. Above, in my code snippet, you can see that in the case of an error, I just log it to my console.

### Conclusion

There is much more I could write about when it comes to promises. There are more methods associated with them and more use cases. You can even construct your own promise objects using the `new` keyword. Check out the youtube video I linked in the resources section to see this in action.

I wanted to keep this blog fairly short, but I might go more in depth on the subject in the future. Let me know how you have used promises in your code. Hope you all are safe and happy!

##### Resources

- [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [Medium Blog by Eric Elliott](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261)
- [A Good Youtube Video on Promises](https://www.youtube.com/watch?v=DHvZLI7Db8E)