Follow me if you want to grow your full-stack JavaScript skills with my screencasts and courses.

The promiseland

Resources

Q on github: https://github.com/kriskowal/q

Strongloop article:Nodejs promises with Q

An old fashioned callback pyramid

Take a look at this pyramid of doom, because the function is asynchronous, it's difficult to compose multiple calls and create dependency between them.

app.js
  
  function generateRandomNumber(cb){
      setTimeout(function(){
          cb(null, Math.floor(Math.random() * 100));
      }, 50);
  }


  generateRandomNumber(function(err, nr1){
      generateRandomNumber(function(err, nr2){
          generateRandomNumber(function(err, nr3){
              generateRandomNumber(function(err, nr4){
                  generateRandomNumber(function(err, nr5){
                      generateRandomNumber(function(err, nr6){
                          generateRandomNumber(function(err, nr7){
                              console.log(nr7 + nr6 + nr5 + nr4 + nr3 + nr2 + nr1);
                          });
                      });
                  });
              });
          });
      });
  });
  

Nested promises

We introduce the q package into the mix, and start using promises. But we still nest the promises, instead of using chaining correctly, as we'll do later on.

app.js
  
  var Q = require('q');

  function generateRandomNumber(cb){
      setTimeout(function(){
          cb(null, Math.floor(Math.random() * 100));
      }, 50);
  }

  var genPromise = Q.denodeify(generateRandomNumber);

  genPromise().then(function(nr1){
      genPromise().then(function(nr2){
          genPromise().then(function(nr3){
              console.log(nr1 + nr2 + nr3);
          });
      });
  });
  

Chained promises

We refactor our nested promises to a much more readable format. We achieve this by using proper promise chaining.

app.js
  
  var Q = require('q');

  function generateRandomNumber(cb){
      setTimeout(function(){
          cb(null, Math.floor(Math.random() * 100));
      }, 50);
  }

  var genPromise = Q.denodeify(generateRandomNumber);

  genPromise(0)
      .then(function(nr){
          return genPromise(nr)
      })
      .then(function(nr){
          return genPromise(nr)
      })
      .then(function(nr){
          return genPromise(nr)
      })
      .then(function(total){
          console.log(total);
      });
  

Wrap up

Promises are amazingly powerful and is also part of the ES6 spec. I wanted to show you how to do it without ES6, because you should be using it already. No need to pull in an ES6 transpiler or wait for browsers and node to catch up.