Failure is inevitable


Practical Promises in JavaScript - What are they, and how do I use them?

JavaScript promises are a concept that I see developers, both pros and novices, struggle with on a regular basis. For those of us that come from a synchronous-programming background, using them effectively and understanding what's happening can be challenging, especially if you don't have a good grasp on all the ways that promises can be manipulated and used. In this new series of posts, we'll be looking at how to use promises effectively.

What is a Promise?

There's no better place to start than at the beginning, right? So what exactly is a promise?

Per the Mozilla Develoepr Network:

A Promise represents a value which may be available now, or in the future, or never.

We need promises because of the asynchronous nature of many JavaScript APIs, including the heavily used XMLHttpRequest: when we call a long-running function, it's result might not be available until later, if at all. When used properly, promises allow us to deal with this in a clean, readable manner.

When a promise is resolved, the resolved value is made available via the promise. So, if we had a long running HTTP request to retrieve a user, once that request completes, we would resolve the promise with the user, which would make the user available to anyone that was waiting for the promise to be resolved.

A promise can also be rejected, indicating that there was a problem, and that the promise will never be resolved. We can optionally hand back a value as part of rejecting the promise, too, and anyone that is watching will receive that value.

Consuming Promises

Before we talk about how to create and use our own promises, let's talk about how to be good consumers of promises.

Let's pretend some function hands us back a promise:

const myPromise = someAsyncLongRunningOperation();

We want to capture the result once it's available. To do that, we use our promise's then function to register a callback function. That callback function will receive the result of the promise, once it's available:

myPromise.then(result => console.log('We got the result: ', result));

What if something goes wrong though, and our promise is rejected? There are actually a couple of ways we could be notified about that. One is to pass a second callback to the then function:

myPromise.then(result => console.log('We got the result: ', result), error => console.log('Bad news, Jim: ', error));

We could also make use of the promise's catch function:

myPromise.catch(error => console.log('Bad news, Jim: ', error));

It's important to understand that these two approaches are not equivalent. There are subtle, important differences in the behavior you'll see. I tend to use catch instead of then(function,function), for reasons I'll explain in a future post

Up Next

I think that's a good starting point. Up next, let's look at creating our own promises!

About Matt Honeycutt...

Matt Honeycutt is a software architect specializing in ASP.NET web applications, particularly ASP.NET MVC. He has over a decade of experience in building (and testing!) web applications. He’s an avid practitioner of Test-Driven Development, creating both the SpecsFor and SpecsFor.Mvc frameworks.

He's also an author for Pluralsight, where he publishes courses on everything from web applications to testing!

blog comments powered by Disqus