Promises — in layman terms

When the whole world says, “Wow! Promises are cool!”, and you are puzzled, “Why is it cool?”, I have also been puzzled the same way. When you ask them why and they throw some words at you like, “asynchronous”, “javascript is single-threaded”, and you stare at them asking, “So what if Javascript is single threaded ??”, then join the club!

Let’s take a look at promises from a top to bottom fashion. Let’s also try to execute the snippets in plunkr/jsfiddle to get a better understanding.

doThisFirst().then(function(resultOfFirst){
doThisNext(resultOfFirst);
});
function doThisFirst(){
return $.getJSON(“sample.json”);
}

Hold on, when we take a look at it, does not it look similar to a synchronous flow of execution?

var resultOfFirst = doThisFirst(); doThisNext(resultOfFirst);

But, sadly this “resultOfFirst” remains undefined. Since javascript keeps executing, not waiting for “sample.json” file to be read.

When we delay the execution, it might work fine.

function doThisFirst(){
var resultOfFirst = $.getJSON(“sample.json”);
window.setTimeout(function (){
alert(“after a few secs”);
alert(JSON.stringify(resultOfFirst) + “ is the data from reading the file”);
}, 2000)
alert(“this gets alerted before the timeout”);
}

Why does it work now? Javascript does not wait for the service call to be finished and it keeps executing. Javascript has a single queue where events wait to get executed. In our case, after the timeout is set, javascript keeps executing subsequent parts of code and after 2 seconds, the file “sample.json” is fetched and and it sends its result to the event queue. Javascript now picks up from the event queue and starts executing. That’s why people say javascript is single threaded. Has a single queue which it waits upon. But, this 2 second timeout may not be the same all the time. So this timeout is a little dangerous and unpredictable.

This piece of code can be made simpler and less dangerous.

function doThisFirst(){ $.getJSON(“sample.json”, function(resultOfReadingTheJSON){
doThisNext(resultOfReadingTheJSON);
}) }

or

function callback(resultOfReadingJSON){ doThisNext(resultOfReadingJSON); }
function doThisFirst(){
$.getJSON(“sample.json”, callback);
}

This is a callback function which notifies the javascript event queue.

If we could co-relate a callback function to something in our real life, it would be our contact details. Let’s say we ask our friend to get a golden ring for us. After she gets it, we would like to test the purity of the golden ring. Our friend might take some time for going to the shop and buying it. Obviously we would like to continue with our tasks and to be notified when she is ready with the ring. So we give her our contact details for calling us back.

Having said all this, how would this help us understanding promises? When we have nested callbacks and dependencies, it might get very difficult to handle error scenarios (pyramid of doom). Hence we use promises for better readability, understanding and debugging(clean code).

In the world of promises, instead of timeouts, we have statuses. The possible statuses of a promise could be,

1. Deferred(waiting for the result)

2. Resolved (with success)
3. Resolved (with failure)

This is how, approximately, the internal of a promise would look like:

function MimicPromise(handler) {
var status = “deferred”; var data = “not set yet”; function resolve(dataFromResponse) { //resolved and successful console.log(“in resolve”); data = dataFromResponse; status = “resolved”; } function reject(err) { //resolved and failure
console.log(“in reject”);
data = “error and in reject”; status = “resolved”; }
handler(resolve, reject);
this.then = function(done){ if(status == “resolved”){
console.log(status + “ is the status”); done(data); } }
}
function doThisFirst(){ return new MimicPromise(function(resolve, reject) { $.getJSON(“sample.json”, function(data){
if(data){
resolve(data)
} else{
reject(data);
} }) }) };
doThisFirst().then(function(resultOfFirst){ console.log(JSON.stringify(resultOfFirst));
});

In this case, if at all we try to access the response before it is resolved, the ‘status’ would be ‘deferred’ and the response data remains unset.

Hope this helps :).