A Coding Writer’s Guide: An Introduction To ES6 Promises

Andrew Ly
The Startup
Published in
4 min readAug 15, 2019

Welcome back to the ‘A Coding Writer’s Guide’ series! If you have been keeping up with this series, you’d know that I recently wrote an article about the differences between ES5 and ES6. In that post I did a brief overview on some of the new features that come with the latest version of JavaScript. So if you don’t know the differences yet, make sure you click on the link and read that puppy before going any further. Now if you did read my previous post, you’re probably wondering why didn’t I go over Promises then? Well, that’s because I felt that it was a topic better reserved for a post on its own.

So here we are. We’ve finally reached the ‘Promised Land’ (and not of biblical proportions per se, but as a new coder perhaps you’ll believe this article to be the gateway entrance into a holy land of code opportunities!).

When I say Promises, I’m not referring to the one of the interlocking pinky variety. Though visualizing a Promise as an abstract concept might help. By that I suggest for all intents and purposes, think of this real-life scenario of keeping your word to a dear friend: They call you up and ask you for help moving their furniture a week from today and being the good friend that you are, you make a promise to do so. Then, when moving day inevitably arrives, you show up to their doorstep and you keep your promise of helping them move. Simple right? Now let’s apply that scenario to code.

So What’s A Promise in JavaScript Exactly?

Promises are used to handle asynchronous operations in JavaScript. They are easy to manage when dealing with multiple asynchronous operations where callbacks can create callback hell leading to unmanageable code.

The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.

Prior to promises events and callback functions were used but they had limited functionalities and created unmanageable code.
Multiple callback functions would create callback hell that leads to unmanageable code. Events were not good at handling asynchronous operations.

Promises are the ideal choice for handling asynchronous operations in the simplest manner.

They can handle multiple asynchronous operations easily and provide better error handling than callbacks and events. To put it simply they make:

  1. Code easier to read/consume
  2. Easier handling of asynchronous operations e
  3. Easier to control flow of asynchronous logic
  4. Easier Error Handling

Types Of Promises

Promises can come in four different states:

  1. Fulfilled
  2. Rejected

3. Pending

4. Settled

Fulfilled: An action related to the promise which succeeded and the fulfillment value is permanently attached to the Promise. This may be any value, including undefined.

p.then(onFulfilled[, onRejected]);

p.then((value) => {
// fulfillment
}, (reason) => {
// rejection
});

Rejected: An action related to the promise which failed and the rejected value is permanently attached to the Promise. As with the fulfilled state, this may also be any value, including undefined, though it is usually an Error object.

p.catch(onRejected);

p.catch(function(reason) {
// rejection
});

Pending: Neither fulfilled nor rejected. This state is transitional and can become one of the two above states.

Settled: The Promise has been either fulfilled or rejected.

p.finally(onFinally);

p.finally(function() {
// settled (fulfilled or rejected)
});

A finally callback will not receive any argument, since there's no reliable means of determining if the promise was fulfilled or rejected. This use case is for precisely when you do not care about the rejection reason, or the fulfillment value, and so there's no need to provide it.

Creating a Promise

A Promise is an object made by using the new keyword and its constructor. This constructor takes a function as its argument, which is known as the "executor function". This function should take two functions as parameters. The first function is invoked when the asynchronous task completes successfully and returns the results of the task as a value. The second function is invoked when the task fails and returns the reason for failure. This is typically conveyed as an error object.

const myFirstPromise = new Promise((resolve, reject) => {
// do something asynchronous which eventually calls either:
//
// resolve(someValue); // fulfilled
// or
// reject("failure reason"); // rejected
});

In order to give a function the promise functionality, you must have it return a promise like so:

function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}

Before I wrap things up, here’s another example of a promise in action just for good measure:

let myFirstPromise = new Promise((resolve, reject) => {
// We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
// In this example, we use setTimeout(...) to simulate async code.
// In reality, you will probably be using something like XHR or an HTML5 API.
setTimeout(function(){
resolve("Success!"); // Yay! Everything went well!
}, 250);
});

myFirstPromise.then((successMessage) => {
// successMessage is whatever we passed in the resolve(...) function above.
// It doesn't have to be a string, but if it is only a succeed message, it probably will be.
console.log("Yay! " + successMessage);
});

And there you have it! I have covered a relatively brief introduction into Promises which should serve you well in all of your asynchronous needs. You now the types of promises, and how to create one on the fly. Now go out there and code!

--

--

Andrew Ly
The Startup

Founder of Neo Typewriter. He is a published author, podcast host, digital marketer, and full-stack web developer. Read more at: www.andrewjly.com