A Brief Introduction to Promises

By November 29, 2016JavaScript
Scout Promise

It took me a while to get used to working with Promises in JavaScript. I fundamentally knew how the jQuery Deferred object worked from years ago, so some of the concepts were familiar to me. But, the beauty of the newer Promise implementations is in how it really cleans up your code by breaking it up into blocks that can then be chained and executed asynchronously.

Consider the following:

The process is kicked off at the bottom with a call to doSomething() . Notice that doSomething()  calls fetchSomething() , and all that fetchSomething()  does is return the results of someHttpClient.get() . But, in this case, suppose that the implementation of get()  returns a Promise, not a value. So, when fetchSomething()  runs, it returns nearly immediately, while the underlying HTTP GET operation that is being performed may take many seconds to actually execute.

The Promise is what allows that long-running GET operation to take place asynchronously. That is, the doSomething()  code is not blocked waiting for the web request to finish running. But, in this case, doSomething()  is also returning the result of fetchSomething() , which is a Promise, so it finishes executing nearly immediately, too, and doesn’t block the original calling code.

Eventually, that web request will complete and an actual value will exist. This is when the Promise is resolved. Everything that was waiting for the value from the get()  operation will receive it via chained then()  functions. The first then()  in the chain above is in the doSomething()  function, which receives the response value from the Promise, and then returns a totally different value.

Now, I said above that doSomething()  returns the result of fetchSomething() , but in reality, it returns the result of calling the chained then()  function on the Promise returned from fetchSomething() , which is itself a Promise (“turtles all the way down” comes to mind here). So, the callback function defined in the then()  is not executed until the Promise is resolved, which in this case, is not until the web request finishes.

The then()  inside the doSomething()  function resolves its Promise by returning the length of the data received from the web request. So, the then()  chained to the doSomething()  call at the bottom will not receive the original response value from the get()  Promise, but rather, will receive a numeric value instead.

What about error handling? The way that my preferred Promise library (Bluebird.js) does this is with a special catch()  convenience method. It works like then()  chaining, but for errors only (i.e., when Promises are rejected as opposed to resolved). In the code above, there is only one catch()  defined, so an error anywhere in the Promise chain will bubble up to be handled in one place.

Without Promises, the logic above would resemble the following synchronous code, which blocks execution each step along the way:

 


Also published on Medium.

The following two tabs change content below.