Show Buttons
Share On Facebook
Share On Twitter
Share On Google Plus
Share On Linkdin
Share On Reddit
Share On Stumbleupon
Contact us
Hide Buttons

JavaScript Promises — Visualized

When you work with javascript, you will often find that call­backs are all over the place. They are in your front end code, in your mid­dle­ware, and in case you use it to inter­face with your data­base, you would have it in your back end code too. Heck, they even come to haunt you in your dreams. One of the clever­est ways to avoid this hell is by using promises. Promises are a rel­a­tively new con­cept in javascript require you to think about your code in a slightly dif­fer­ent, yet inter­est­ing way.

I recently had the oppor­tu­nity to mess around with promises a lot. In this post, I will just touch upon some of ways I ended up using promises and pro­vide those snip­pets for quick reuse.

Look at the fol­low­ing visu­al­iza­tion now, and then look at it again at the end of this post. It explains how the func­tions are asso­ci­ated when you cre­ate new promise obejcts.

Promises Visualized

I am not going to go into detail of what promises are and its dif­fer­ent use cases. You can always read this amaz­ingly long arti­cle on html5rocks for that. How­ever, if you dont have the time, this arti­cle should at least help you to address the mat­ter at hand.

So, how do you cre­ate a promise?

var getData = new Promise(function(resolve, reject){

    // Do something asynchronous and pass it a callback
    getDataFromAMillionMilesAway(function(data){

        if(data){
            resolve(data);
        }
        else {
            reject(new Error("Thats too far away"));
        }

    }); 

});

// And here's how you'd use it

getData().then(function(data){
    console.log('Got Some Data! ', data);
});

As you can see above, the first func­tion passed to the then() func­tion receives the value that you pass to the resolve() func­tion. So what hap­pens to the error case? Well, we didnt cap­ture it in the above exam­ple. But just like the promise con­struc­tor, the then func­tion can take two func­tions are argu­ments. The first func­tion is invoked upon call­ing resolve, and the sec­ond one is invoked upon call­ing reject with the cor­re­spond­ing parameters.

getData().then(
    function(data){
        console.log('Got Some Data! ', data);
    },
    function(error){
        console.log('Something really bad happened :( ', data);
    }
);

So that takes care of the prob­lem of func­tions. You might won­der what good is the promise if you need to call the get­DataFro­mAMil­lion­Mile­sAway func­tion with a para­me­ter. Well, clo­sures to the rescue.

var getData = function(config){

    return new Promise(function(resolve, reject){

        // Do something asynchronous and pass it a callback
        getDataFromAMillionMilesAway(config, function(data){

            if(data){
                resolve(data);
            }
            else {
                reject(new Error("Thats too far away"));
            }

        }); 

    });

}

Note that in this case, we are return­ing the new Promise from the get­Data func­tion. This effec­tively makes get­Data a promise which retains the value of the ‘con­fig’ in a clo­sure using which you can call the then func­tion just like before.

One might argue that this is just a sug­ar­coat on call­backs because as you can see, we are not avoid­ing call­backs alto­gether. In fact, they are they most impor­tant part that lead to either the res­o­lu­tion or rejec­tion of a promise. How­ever, by encap­su­lat­ing the call­back logic in a sin­gle place you can now write much cleaner code like this.

getData(config1)
  .then(function () {
    return getData(config2);
  })
  .then(function ()  {
    return getData(config3);
  })
  .then(function(){
    console.log('All the data was fetched sequentially.');
  });

That looks much more like plain Eng­lish, doesn’t it? You might have just delayed your inevitable bald­ness by a few years.
And that is why promises are so awe­some. They save your hair.

The other impor­tant thing about promises is that you can return a value from a func­tion to resolve a promise with that value. For exam­ple, the fol­low­ing code works per­fectly fine

getData(config).then(function(data){
     data = _.extend({}, data, {'key','valye'});
     return data;
}).then(function(modifiedData){
    console.log(modifiedData);
});

Since all you need is to return a value to resolve a promise, any func­tion that returns a sin­gle value can be used as an argu­ment to the then() func­tion. E.g. Here’s what I mean

getData(config)
    .then(function(data){
        return JSON.parse(data);
    })
    .then(function(parsedData){
        console.log(parsedData);
    });

//is equivalent to

getData(config)
    .then(JSON.parse)
        .then(function(parsedData){
            console.log(parsedData);
    });

Once you get a taste of it, I promise you, you will not want to call back 😉

Ryan Sukale

Ryan is just a regular guy next door trying to manage his life and finances.

You may also like...