Promises in ES6

Friday, October 23, 2015

Overview

Promises have been around in JavaScript in one form or another for a while now, but they are typically provided by a framework. For example, if you ever used the jQuery ajax function to make an API call, behind the scenes you were using jQuery's promise mechanism.

In this example, the "ajax" function returns a promise that when it is fulfilled fires the "done" function.

Now, with the release of the new EcmaScript 6 standards, promises are now a part of the JavaScript language.

My Bad Promise Analogy

One of my favorite restaurants to stop at on long road trips is The Cracker Barrel. Often times, they are super busy, and while there I will have to check in at the hostess stand. Typically, they write my name and down and give my a buzzer that will go off when a table is ready. In the mean time I can walk around their gift shop and if I see something cool (usually a ridiculous looking hat) I can buy it. Once the buzzer goes off, I hand the buzzer to the hostess and they then take my family and I to a table where I invariably eat too many biscuits.

In this case, that buzzer that was given to me represents a promise. It is a promise to fulfill something, and in the meantime, I can go about my business doing other things. The act of taking my family to the table at a later time is fulfilling that promise.

This is similar to how a promise works. You make an asynchronous call to do something and you are immediately returned a promise. At a later time, when that asynchronous task completes, it will fulfill the  promise, and execute the code to handle the returned response.

The Different States

  • When a promise is first created and before it has not been "settled", it is in a pending state.
  • When a promise finishes its asynchronous task and has a successful resolution, the promise is changed to the fulfilled or resolved state.
  • When a promise finishes and the task has failed, the promise is changed to the rejected state.
  • Once a promise is fulfilled or rejected, it cannot be changed to any other state. The promise is "settled".

Basic Example

Let's look a basic promise example.

To create a promise, I instantiate a new promise and pass in two callback functions. The first function will fire if when the asynchronous task is successful, the second callback will fire if the asynchronous task fails.

The doSomething function will execute and the code execution will continue executing passed this section. The "then" function executes when the doSomething finishes its asynchronous task.

Using Promises with windows.fetch.

In a more realistic example, Promise will be mostly used with API calls and one way to make an API call is with fetch function that has recently been added to the windows object. The fetch object itself returns a native JavaScript promise so the two objects work well together.

The fetch function returns a promise that when resolved, returns a response. If that response has JSON data in it, then it needs to be serialized, so that serialization function "json()" also returns a promise.

Chaining a Promise

One of the nice feature of Promises, is when the "then" function is fired, it returns a new promise just like the first promise. This makes it easy to treat multiple asynchronous tasks synchronously.

So in the above example, I am calling addYada function repeatedly three times in sequential order and not all at the same time by placing each subsequent call in the "then" function.

The "All" Static Function

There are circumstances where I need to make several API calls. I want to make them all at once, but I don't want to do anything until I get the last API response.

In this case use the Promise.All() function manage the promises.

The "All" promise returns an array of the resolved promises.

The "Race" static function

Say I have a load-balanced environment, and I want to make the same API calls to several servers to get the fastest response possible. I want to execute the first call to come back. In this scenario I could use the "Race" static function. The race function takes several promises like the "all" function, but when the first response is resolved, the race function executes.

The "Resolve" static function

I often find my self writing functions that first check a caching mechanism for a value before I actually make an API call. However, the problem I run into is that typically the value retrieved from cache is synchronous while the value retrieved from API call is asynchronous. The cached version will not have a promise associated with  it so I have nothing to resolve at this point.

In this case, I use the Resolve function. The resolve function creates a promise and resolves it immediately. I can use this to pass the value from cache and return it to the client.

The Reject static function

Like the Resolve static function, there are times I want to handle an API call failure by logging the error first and then pass it back to the UI.

By returning the rejected promise, I am ensuring that the UI is getting a settled promise back and it can so something to let the user know.

comments powered by Disqus