Promises – Part 2 – Promise definition

Hopefully part 1 made it clear why promises can be useful in an asynchronous language like JavaScript. I think it’d now be best to talk a bit more about what a promise is and how exactly it works.

A promise is an object that defers a future state in the same way a callback can be used and is a cleaner alternative. To clarify what I mean by cleaner, there is a concept in programming known as “Callback Hell” which describes when functions become nested and difficult to read through the use of callbacks, here’s an example:

a(function (resultFromA) {
    b(resultFromA, function (resultFromB) {
        c(resultFromB, function (resultFromC) {
            d(resultFromC, function(resultFromD) {
                console.log(resultFromD);
            })
        })
    ))
});

You probably get the idea that with more complex functions, this can get messy fast! (Check out callbackhell.com for a more thorough explanation)

Returning to what a promise is, a promise is a placeholder object that represents the result of an asynchronous operation. It holds the current status of the operation and can notify us when the operation either succeeds or fails. A promise can exist in three different states:

  • Pending – the promise’s outcome hasn’t yet been determined, because the asynchronous operation that will produce its result hasn’t completed yet.
  • Fulfilled – the asynchronous operation has completed, and the promise has a value.
  • Rejected – the asynchronous operation failed, and the promise will never be fulfilled. In the rejected state, a promise has a reason that indicates why the operation failed.

(These definitions were taken from Spring.IO)

The only state that a promise can change from is pending to either fulfilled or rejected and once it reaches that point, it can not change again.

Promises have a .then() method which can be used to handle the eventual result of the operation and takes one parameter as a function to execute after the promise has resolved.

In the event that a promise is rejected, a .catch() method can be used as an error handling function, like so:

promiseValue.then(function(value) {
    console.log(value);
}).catch(function(error) {
    console.log("There was an error", error);
});

The .then() method returns another promise which means it is possible to chain this method resulting in a chain of promises without having to nest the functions and avoiding the problems we would face with a series of callbacks.

Promises can be created using new Promise which then takes a function. This function takes two parameters: resolve and reject. These are methods that signify the promise is fulfilled. Any errors should be passed to reject(). Data that has been successfully retrieved should be passed to resolve(), if you need to use it. Otherwise, you can call resolve() with nothing passed in if this does not matter. Here is an example using the ES6 version of promises for how this would look:

var promiseValue = new Promise(function(resolve, reject) {
    asyncFunctionWithCallback(function(err, data) {
        if (err) return reject(err);
        return resolve(data);
    });
});

 

Promises are being introduced as first-class language features in ES6 and alternatively there are different JavaScript libraries which can handle promises such as Q, RSVP, when or even jQuery. I’ll begin looking at these libraries in the next post.

Thanks for reading! If you’ve got any comments, I’d love to hear from you.

Promises:

Further reading:

Advertisements

Promises – Part 1 – Asynchronous Code

Before I get stuck in to explaining promises, there’s another programming concept I need to go over first; synchronous and asynchronous code. The JavaScript language is asynchronous, which means that it is possible for a block of code to continue running while an asynchronous call is made. Here is a block of JavaScript to help illustrate this concept:

console.log("First");
setTimeout(function() {
    console.log("Second");
}, 200);
console.log("Third");

The output of this code would be:

First
Third
Second

What should come across here is that when the code runs, it does not wait for the setTimeout to finish before executing console.log(“Third”), this is asynchronous code in action!

At first glance this seems a bit dangerous and maybe a bit confusing because it feels like you have less control of how the code executes. In reality though, this allows JavaScript to operate without having to worry about ‘Blocking Functions’.

A Blocking Function is code that will stop the execution of a program until it finishes (also called a synchronous call). This means that if you were performing an AJAX request that was receiving a large amount of data, the request would idle the rest of the program until it had completed, possibly slowing load times. If the call were asynchronous however, the server could continue executing the rest of the program while the AJAX request loaded.

This may have occurred to you while reading the preceding paragraphs, but what if you needed the data back from that AJAX request before you could continue executing the rest of the program? You’d essentially be stuck because your code would fail when it tries to access the data that doesn’t exist yet.

This is exactly where promises come in handy! A promise is a way of asking the code to let you know when an asynchronous process has been completed and then run a different block of code, while still allowing the rest of an application to run.

That’s it for part one which has set the scene for promises and hopefully given you an understanding of asynchronous code and how we can use it. In the next part, I’ll begin looking at callbacks vs promises, ES6 promises and the various JS promise libraries we have at our disposal.

Promises: