Promises in ES6

In JS world, promises always been a controversial topic. Interestingly, There are lots of libraries out there implementing promise in there own tastes. jquery’s deferred, q, bluebird, deferred.js to name just a few. Opinions conflict over using async, generators, callbacks etc. But thank God; ECMA has now officially implemented promises in ES6. That’s a good news for JS community over having a single standard implementation of promises.

IoT

Promises are in a way clean implement async programming in JavaScript (ES6 new feature). Prior to promises, callbacks were used to implement async programming.

Let’s dive in to first understand what async programming is?

Understanding Callback

Callback are most of the time a function passed into another function as a parameter and is called subsequently, if conditions of calling is met. This mechanism is known as callback.

Here is how it looks

var isWrittenToDisk;
function writeDone (){
   console.log("Writing to disk is done.");
};
function writeFailed (){
   console.log("Writing to disk has failed.");
};
function notifyWriteStatus (done, fail){
   if(isWrittenToDisk){
      done();
   } else {
      fail();
   }
};
// typically this should be set in function writing to
// file, but for sake of simplicity we are assigining it
// to true
isWrittenToDisk = true;
notifyWriteStatus(writeDone, writeFailed);
console.log("Process is done!")

It would have output, similar to following

Writing to disk is done.
Process is done!

IoT

In notifyWriteStatus method above calles appropriate method as per flag set in isWrittenToDisk. If isWrittenToDisk set to true, done callback is called, else fail callback

The above code snippet is synchronous and hence blocks the execution until a file written to disk. To overcome this we used to use non-blocking/asynchronous callbacks

In ES5 or before one can achieve async calls by wrapping them within setTimeout method, that’s async by default.

Let’s conver above example to async call

var isWrittenToDisk;
function writeDone (){
   console.log("Writing to disk is done.");
};
function writeFailed (){
   console.log("Writing to disk has failed.");
};
function notifyWriteStatus (done, fail){
   setTimeout(function(){
      if(isWrittenToDisk){
         done();
      } else {
         fail();
      }
   }, 3000);
};
// typically this should be set in function writing to
// file, but for sake of simplicity we are assigining it
// to true
isWrittenToDisk = true;
notifyWriteStatus(writeDone, writeFailed);
console.log("Process is done!")

It would have output, similar to following

Process is done!
Writing to disk is done.

The setTimeout will wait for 3 seconds before executing notifyWriteStatus method body. meanwhile our main program would be done executing

But, it becomes tedious to maintain when there are multiple nested callbacks, looks scary. And that’s where “callback hell” kicks in

ES6 Promises

ES6 comes to one’s rescue by introducing the concept of promises. Promises in nutshell are, continuing event; helping us to execute multiple async ops together as chained. Promises returns promise instance that can be chained and passed on to chained function.

Let’s dive in

new Promise ((resolve, reject) => {
  if (Math.random() * 10 <= 9) {
    resolve('Yay!');
  }
  reject(new Error('I failed!'));
}).then (
  (resolveValue) => { console.log(resolveValue) },
  (error) => { console.log(error) }
)

In example above, promise object returns a promise and passes onto next then function that, in turn passes function to be called on resolve or reject state and passes it to caller.

Promises can be chained multiple times, the only condition is that return value should be an object of promise. Let’s see

function randomRoll(){
   return new Promise ((resolve, reject) => {
     if (Math.random() * 10 <= 9) {
       resolve('Yay!');
     } else {
      reject(new Error('I failed!'));
     }
   })
};
randomRoll()
   .then(
      (resolveValue) => {
         console.log("Done. Redoing...");
         randomRoll();
      },
      (rejectValue) => {
         console.log("Failed. Miserably :(");
         randomRoll();
      }
   ).then(
      (resolveValue) => {
         console.log("Done. Resting...");
      },
      (rejectValue) => {
         console.log("Failed. Miserably :( Again!!");
      }
   )

ES6 comes to your rescue by introducing the concept of promises. Promises are “Continuation events” and they help you execute the multiple async operations together in a much cleaner code style.

Happy Coding <3