JavaScript is a language of the Web. This series of articles will talk about my observations learned during my decade of software development experience with JavaScript.

Introduction

A Promise is an asynchronous operation that has not completed now but will complete in the future. ES6 has adopted promises implementation as native APIs. The promise gives us a guarantee to return the value in the future. Promises are not like events where you need to bind the event with a particular method.

Creating a promise

The way to create a Promise is by using "new Promise" constructor, which accepts two callback functions as parameters. The first typically named resolve is a function to call with the future value when promise is ready. The second typically named reject is a function to reject the Promise if it cannot resolve the future value.
Syntax
As per MDN, below is the syntax:
new Promise( /* executor */ function(resolve, reject) { ... } );
Executor: A function that will be passed to other functions via the arguments resolve and reject.
Sample code
  1. var p1 = new Promise(function(resolve, reject)
  2. {
  3. if ( /* condition */ )
  4. {
  5. resolve( /* value */ ); // promise fulfilled
  6. }
  7. else
  8. {
  9. reject( /* reason */ ); // mention reason for rejection
  10. }
  11. });
Let us see what happens at Browser after we trigger the above code.

Summary of Promise states

Prototype promise methods

After a Promise is created, we need to pass around the value of this Promise. Inorder to consume a Promise value we attach a handler using via the below methods.
Two methods of Promise are associated with constructor prototype Promise.prototype these are:

then() method

It returns a promise with two arguments, i.e., onFulfilled, on Rejected
Example- it will print “Fulfilled!” because we’ve set flag = true,
  1. var flag = true;
  2. var p1 = new Promise(function(resolve, reject)
  3. {
  4. if (flag)
  5. {
  6. resolve("Fulfilled!");
  7. }
  8. else
  9. {
  10. reject("Rejected!");
  11. }
  12. });
  13. p1.then(function(value)
  14. {
  15. console.log(value); // Fulfilled!
  16. }, function(reason)
  17. {
  18. console.log(reason); // Rejected!
  19. });

catch() method

It returns a promise and deals with rejected cases only. If you pass null or undefined in .then() method first argument it .then() method behaves like .catch() method.
Example- Below code will print “Rejected!”
  1. var flag = false;
  2. var p1 = new Promise(function(resolve, reject)
  3. {
  4. if (flag)
  5. {
  6. resolve("Fulfilled!");
  7. }
  8. else
  9. {
  10. reject("Rejected!");
  11. }
  12. });
  13. p1.then(function(value)
  14. {
  15. console.log(value); // Fulfilled!
  16. }).catch(function(reason)
  17. {
  18. console.log(reason); // Rejected!
  19. });
Example- Chaining promises via .then() method.
As .then(), .catch() methods return Promise so we could chain these [please refer Voice of a Developer JavaScript Chaining part 16 to understand Chaining].
Example- chaining of .then() method and incrementing counter.
  1. var counter = 0;
  2. var p1 = new Promise(function(resolve, reject)
  3. {
  4. resolve(counter);
  5. });
  6. p1.then((value) =>
  7. {
  8. console.log('Counter: ' + ++counter); // 1
  9. }).then((value) =>
  10. {
  11. console.log('Counter: ' + ++counter); // 2
  12. }).then((value) =>
  13. {
  14. console.log('Counter: ' + ++counter); // 3
  15. }).catch(function(reason)
  16. {
  17. console.log(reason);
  18. });
Output

Promise methods

Promise.all()- When you are working with multiple promises, this function is really helpful. Once all Promises are resolved or rejected, it returns Promises.
  1. var p1 = new Promise(function(resolve, reject) {
  2. var counter = 0;
  3. resolve(++counter);
  4. });
  5. var p2 = new Promise(function(resolve, reject) {
  6. resolve("counter 2");
  7. });
  8. var p3 = new Promise(function(resolve, reject) {
  9. setTimeout(resolve("Promise 3"), 5000); //5000 milisecond = 5 sec
  10. });
  11. Promise.all([p1, p2, p3]).then(function(values) {
  12. console.log(values); // Output: [1, "counter 2", "Promise 3"]
  13. }).catch((val) => {
  14. console.log(val); // return “rejected”, if any promise fails
  15. });
Once all Promisesp1, p2, p3 are fulfilled.then() method is called. The above code .then()will execute after 5 seconds when all Promises are resolved (after setTimeout).
If any promise returns reject, then it will return “rejected”.
Promise.race()- It returns a Promise which resolves or reject first. It accepts an iterable of Promises and works like OR condition.
  1. var p1 = new Promise(function(resolve, reject)
  2. {
  3. setTimeout(resolve, 1500, "resolved - will not get printed");
  4. });
  5. var p2 = new Promise(function(resolve, reject)
  6. {
  7. setTimeout(reject, 100, "rejected - printed");
  8. });
  9. Promise.race([p1, p2]).then(function(value)
  10. {
  11. console.log(value); // not get printed
  12. }, function(reason)
  13. {
  14. console.log(reason); // rejected - printed
  15. // p6 is faster, so it rejects
  16. });

Load XMLHttpRequestfiles

The use of Promises is by using XMLHttpRequestAPI asynchronously. It loads file in the background, example: it will load two JSON files via XHR requests:
automobile.json
  1. {
  2. "automobile": [
  3. {
  4. "vehicle": "car",
  5. "engine": "1200cc"
  6. },
  7. {
  8. "vehicle": "bike",
  9. "engine": "200cc"
  10. },
  11. {
  12. "vehicle": "jeep",
  13. "engine": "2000cc"
  14. }]
  15. }
employee.json
  1. {
  2. "employees": [
  3. {
  4. "firstName": "John",
  5. "lastName": "Doe"
  6. },
  7. {
  8. "firstName": "Anna",
  9. "lastName": "Smith"
  10. },
  11. {
  12. "firstName": "Peter",
  13. "lastName": "Jones"
  14. }]
  15. }
Script.js
  1. varary = ['http://localhost/automobile.json', 'http://localhost/employee.json']
  2. var p1 = new Promise(function(resolve, reject)
  3. {
  4. letsrcurl = getJSON(ary[0], resolve);
  5. });
  6. var p2 = new Promise(function(resolve, reject)
  7. {
  8. letjson = getJSON(ary[1], resolve);
  9. });
  10. functiongetJSON(json, resolve)
  11. {
  12. varxmlhttp = new XMLHttpRequest(json);
  13. xmlhttp.open("GET", json);
  14. xmlhttp.send();
  15. xmlhttp.onload = function()
  16. {
  17. if (xmlhttp.status === 200)
  18. {
  19. resolve(xmlhttp.responseText);
  20. }
  21. }
  22. };
  23. Promise.all([p1, p2]).then((val) =>
  24. {
  25. document.getElementById('div2').innerHTML = val;
  26. });
Output: it will load data of ‘val’ into ‘div2’ of HTML.

Promises Advantages

This is solved and simplified via Promise prototypal methods & chaining.
  1. var p1 = new Promise().resolve('resolve');
  2. p1.then((value) =>
  3. {
  4. console.log(value);
  5. }).then((value) =>
  6. {
  7. console.log(value);
  8. }).then((value) =>
  9. {
  10. console.log(value);
  11. }).then((value) =>
  12. {
  13. console.log(value);
  14. });

Libraries providing Promises

Promises are supported via different libraries Q, AngularJS, BlueBird, etc. There are many libraries providing promises as an abstraction on top of JavaScript Native Promises API, e.g.
Q.js
  1. var functionA = function()
  2. {
  3. return "ret A";
  4. };
  5. var functionB = function()
  6. {
  7. return "ret B";
  8. };
  9. var promise = Q.all([Q.fcall(functionA), Q.fcall(functionB)]);
  10. promise.spread(finalStep);
AngularJS
  1. // Simple GET request example:
  2. $http(
  3. {
  4. method: 'GET',
  5. url: '/someUrl'
  6. }).then(function successCallback(response)
  7. {
  8. // this callback will be called asynchronously
  9. // when the response is available
  10. }, function errorCallback(response)
  11. {
  12. // called asynchronously if an error occurs
  13. // or server returns response with an error status.
  14. });
It generates an HTTP request and returns a response.

Summary

Please share your feedback/comments.
<< Voice of a Developer: JavaScript Web App Performance Best Practices - Part Thirty-One