Promises

Understanding Promises

A Promise in short:

"Imagine you are a kid. Your mom promises you that she'll get you a new phone next week."

You don't know if you will get that phone until next week. Your mom can either really buy you a brand new phone, or stand you up and withhold the phone if she is not happy.

That is a promise. A promise has 3 states. They are:

  • Promise is pending: You don't know if you will get that phone until next week.
  • Promise is resolved: Your mom really buy you a brand new phone.
  • Promise is rejected: You don't get a new phone because your mom is not happy.

Creating a Promise

/* ES5 */
var isMomHappy = false;

// Promise
var willIGetNewPhone = new Promise(
 function (resolve, reject) {
  if (isMomHappy) {
   var phone = {
    brand:'Samsung',
    color:'black'
   };
   resolve(phone); // fulfilled
  } else {
   var reason = new Error('mom is not happy');
   reject(reason); // reject
  }
 }
);

The code is quite expressive in itself.

  • We have a boolean isMomHappy, to define if mom is happy.

  • We have a promise willIGetNewPhone. The promise can be either resolved (if mom get you a new phone) or rejected (mom is not happy, she doesn't buy you one).

  • There is a standard syntax to define a newPromise, refer to MDN documentation.

    // promise syntax look like this
    new Promise( /* executor */ function(resolve, reject) { ... } );
    
  • What you need to remember is, when the result is successful, call resolve(your_success_value), if the result fails, call reject(your_fail_value) in your promise. In our example, if mom is happy, we will get a phone. Therefore, we call resolve function with phone variable. If mom is not happy, we will call reject function with a reason reject(reason)

Consuming Promises

Now that we have the promise, let's consume it.

/* ES5 */
...

// call our promise
var askMom = function () {
    willIGetNewPhone
        .then(function (fulfilled) {
            // yay, you got a new phone
            console.log(fulfilled);
         // output: { brand: 'Samsung', color: 'black' }
        })
        .catch(function (error) {
            // oops, mom don't buy it
            console.log(error.message);
         // output: 'mom is not happy'
        });
};

askMom();
  • We have a function call askMom. In this function, we will consume our promise willIGetNewPhone.

  • We want to take some action once the promise is resolved or rejected, we use.thenand.catchto handle our action.

  • In our example, we havefunction(fulfilled) { ... }in.then. What is the value offulfilled? Thefulfilledvalue is exactly the value you pass in your promiseresolve(your_success_value). Therefore, it will bephonein our case.

  • We havefunction(error){ ... }in.catch. What is the value oferror? As you can guess, theerrorvalue is exactly the value you pass in your promisereject(your_fail_value). Therefore, it will bereasonin our case.

Chaining Promises

Promises are chainable.

Let's say, you, the kid, promise your friend that you will show them the new phone when your mom buy you one.

That is another promise. Let's write it!

// 2nd promise
var showOff = function (phone) {
    return new Promise(
        function (resolve, reject) {
            var message = 'Hey friend, I have a new ' +
                phone.color + ' ' + phone.brand + ' phone';

            resolve(message);
        }
    );
};
  • In this example, you might realize we didn't call the reject. It's optional.

  • We can shorten this sample by using Promise.resolve instead.

// 2nd promise
var showOff = function (phone) {
    var message = 'Hey friend, I have a new ' +
                phone.color + ' ' + phone.brand + ' phone';

    return Promise.resolve(message);
};

Let's chain the promises. You, the kid can only start the showOff promise after the willIGetNewPhone promise.

// call our promise
var askMom = function () {
    willIGetNewPhone
    .then(showOff) // chain it here
    .then(function (fulfilled) {
            console.log(fulfilled);
         // output: 'Hey friend, I have a new black Samsung phone.'
        })
        .catch(function (error) {
            // oops, mom don't buy it
            console.log(error.message);
         // output: 'mom is not happy'
        });
};

That's how easy to chain the promise.

Promises are Asynchronous

// call our promise
var askMom = function () {
    console.log('before asking Mom'); // log before
    willIGetNewPhone
        .then(showOff)
        .then(function (fulfilled) {
            console.log(fulfilled);
        })
        .catch(function (error) {
            console.log(error.message);
        });
    console.log('after asking mom'); // log after
}

What is the sequence of expected output? Probably you expect:

1. before asking Mom
2. Hey friend, I have a new black Samsung phone.
3. after asking mom

However, the actual output sequence is:

1. before asking Mom
2. after asking mom
3. Hey friend, I have a new black Samsung phone.

Why? Because life (or JS) waits for no man.

You, the kid, wouldn't stop playing while waiting for your mom promise (the new phone). Don't you? That's something we call asynchronous, the code will run without blocking or waiting for the result. Anything that need to wait for promise to proceed, you put that in .then.

results matching ""

    No results matching ""