Using the Promise Object with Javascript

I haven’t had to use the Promise function constructor much, I think maybe I’ve used it a handful of times. I don’t know if this is a bad thing. To be honest, the concept of promises is still a bit fuzzy to me. I’d like to build more applications utilizing this construct but I haven’t had to write any programs that run too many asynchronous operations. Or, the need for it wasn’t necessary and I got away with writing a bunch of function callbacks. But that’s what Promises were made for – to eliminate what developers describe as “callback hell” – basically what you get is a chain of nested callbacks which makes for “unnecessary inefficient bloat”. Yeah that’s exactly what I called it.

Ok so this is a continuation of the Advanced Javascript series from TechSith So credit to TechSith for the examples provided on this post.

To simplify the idea of promises in Javascript, we can think of a sequential scenario in which one task needs to finish before starting a new one. I was going to come up with my own example but the “Clean Room” example described in the video makes it super simple to understand so let’s go with that.

Since we are using the ‘new’ keyword in constructing an object, the ‘new Promise’ constructor will return an object. Our initial variable declaration of ‘promiseToCleanTheRoom’ is like setting up or configuring the conditions of our promise. That’s the way I see it – makes it easy to understand. So you try coming up with your analogy, I find that this helps.


let promiseToCleanTheRoom = new Promise(function(resolve, reject) {

        // clean the room

        let isClean = true;

        if (isClean) {
                resolve('Clean');
        } else {
                reject('not Clean');
        }

});

promiseToCleanTheRoom.then(function(fromResolve) {

        // Outputs: the room is Clean
        console.log('the room is ' + fromResolve);

}).catch(function(fromReject) {

        // Outputs: the room is not Clean
        console.log('the room is ' + fromReject);

});   

So it’s only until we use start using “promiseToCleanTheRoom.then()…” when we actually start seeing the Promise object shine. Instead of nesting callbacks, we instead use the then() method to chain our callbacks which makes for much cleaner code. Again, the key thing to note is that we first set things up using the new Promise() function constructor, which takes in an anonymous function as its argument.

Alright, we got our feet wet with a super simple example. I think we’re ready to dive into something a bit more complex. In our next example, were going to use the same sequential scenario but this time the steps are going to be the following:

* Clean Room
* Remove Garbage
* Win Ice Cream

So basically, we start with cleaning the room, then removing the garbage, then as a reward we get some ice cream. It’s important to keep in mind that we can’t skip to our next task before finishing the first task. There is a way to actually get around this – but for this example were going to do things sequentially.


// a bit more complex example
// need to finish a task
// before starting a new task

// Clean room example

let cleanRoom = function() {
        return new Promise(function(resolve, reject) {
                resolve('Cleaned The Room');
        });
};

let removeGarbage = function(message) {

        return new Promise(function(resolve, reject) {
                resolve(message + ' Remove Garbage');
        });
};

let winIceCream = function(message) {

        return new Promise(function(resolve, reject) {
                resolve(message + ' won Ice cream');
        });

};

cleanRoom().then(function(result) {

        return removeGarbage(result);

}).then(function(result) {

        return winIceCream(result);

}).then(function(result) {

        console.log('finished ' + result);

});

Right I know, there’s a lot going on here. But after observing the code myself, this is a much cleaner approach than nesting callbacks.

So let’s break it down

First, we declare our functions and store them in separate task related variables. In this case – we have:

* cleanRoom
* removeGarbage
* winIceCream

The Set Up

We set up our logic and related parameters first. Each variable is assigned a function which then returns a new Promise object. That’s the set up.

Invoking our functions

Once our variables are all set up we can then invoke each of them and chain each one using the then() method.

The all() and race() methods

Two useful methods when when we want a bit more control with our returned Promise. Here’s how these methods are used.

Using all(), each function are all run at the same time-


Promise.all([cleanRoom(), removeGarbage(), winIceCream()]).then(function() {
        console.log('all finished');
});

Using race(), we are expecting that at least one operation or function has at least finished-


Promise.race([cleanRoom(), removeGarbage(), winIceCream()]).then(function() {
        console.log('one of them has finished');
});

With both the all() and race() methods we directly call the “Promise” object and pass our functions in an array object.

Hope this made sense – I think this is one of the more not so easy to understand concepts in Javascript. One way to get really good at using Promises is to use it in a real web application. Next time you find yourself nesting your callbacks, use a Promise instead – even though it’s only a few callbacks.