Promise In JavaScript

In this article, I explain the concept of Promise in JavaScript: its use and its difference from a normal callback function.

 
 
This is the meaning of promise that I found on Bing: "a particular thing that will happen."  But then there is a problem, not all promises are fulfilled.
 
So basically when we make a promise there are two possibilities --  either the promise is fulfilled or not.
 
Promise in JavaScript is used to represent any operation that is deferred or is expected to be completed in future, like an asynchronous ajax request. The syntax goes as given below,
  1. var objPromise = new Promise(function (fulfilled, reject) {    
  2.          //Your codes goes here    
  3. });    
The function passed a parameter to the Promise function known as the executor. The executor function has two parameters which are other callback functions.
 
As discussed above a  promise may have two possible outputs:
  1. Either the Promise is Fulfilled or
  2. Promise is not Fulfilled i.e rejected 
So a promise is in one of these states:
  1. pending (the operation is pending)
  2. fulfilled (the operation is completed successfully)
  3. rejected (the operation failed) 
If the operation is competed successfully then the fulfilled function is to be called or the rejected function is to be called. 
Example:
  1. var objPromise = new Promise(function (fulfilled, reject) {  
  2.       $.ajax({  
  3.          url: "/JSON/states.json",   
  4.          success: function(result){  
  5.               fulfilled(result);  // on success call the fulfilled function  
  6.          }  
  7.          error: function(error){  
  8.               reject(error);      // on error call the reject function  
  9.          }  
  10.      });  
  11. });  
The above-made promise makes an ajax call to retrieve a list of states from a Json file, now either the ajax request will retrieve the list of states or it will fail to do the same. If successful the fulfilled method is called and the result is passed to it as a parameter and in case of any error the reject function is called and the object of error is passed to the reject function.
 
Now that we have created the promise, we can use it by using the method "then" and "catch" which will return the promise.
Example:
  1. objPromise().then(function(data) {       
  2.                    //Code on fulfillment
  3.              })      
  4.             .catch(function(error){      
  5.                   //Code on rejection
  6.              });      
  7.     
  8. ////OR/////    
  9. objPromise().then(function(data) {    
  10.                     //Code on fulfillment   
  11.              }, function(error){    
  12.                     //Code on rejection   
  13.              });    
Now that you know what Promises are, you may practically think that why should one use a promise as it is just another callback function.
So to recognize the need of promise, le'ts consider a scenario where we want to bind two dropdowns; one with list of states and another list of its corresponding city.
Note: I am using ItemTemplate.js to bind the HTML object.
 
So the traditional way of doing this would be...
  1. $(document).ready(function () {    
  2. //get list of states and bind it to #ddlState   
  3.            $.get('/JSON/state.json'function (data) {    
  4.                $('#ddlState').itemTemplate({    
  5.                    dataSource: data    
  6.                });    
  7.            });    
  8. //onChange of #ddlState get list of Cities, filer it and bind it to the element with id #ddlCity  
  9.           $('#ddlState').change(function () {    
  10.                $.get('/JSON/city.json'function (data) {    
  11.                    var filteredData = [];    
  12.                    filteredData = filterCityByState(data);    
  13.                    $('#ddlCity').itemTemplate({    
  14.                        dataSource: filteredData    
  15.                    });    
  16.                });    
  17.            });    
  18.        });    
  19.    
  20. //filter the list of cities belonging to the selected state  
  21.        function filterCityByState(data) {    
  22.            var filteredData = [];    
  23.                $.each(data, function (index, item) {    
  24.                    if (item.stateId == $('#ddlState').val()) {    
  25.                        filteredData.push(item);    
  26.                    }    
  27.                });    
  28.                return filteredData;    
  29.        }    
Now to increase the significance of this example I have introduced a latency of three seconds to the filter function called filterCityByState,
  1. function filterCityByState(data) {  
  2.             var filteredData = [];  
  3.             setTimeout(function () {  
  4.                 $.each(data, function (index, item) {  
  5.                     if (item.stateId == $('#ddlState').val()) {  
  6.                         filteredData.push(item);  
  7.                     }  
  8.                 });  
  9.             }, 3000);  
  10.         return filteredData;  
  11. }  
Now if you go and debug the code, you will find that the function inside the setTimeout is executed three seconds after all the code is executed outside the setTimeout function. So basically the setTimeout function deferred/delayed the execution of the code inside it which filtered the data, hence returning a blank array.
 
So to overcome this problem one can remove the setTimeout function or use a promise instead. 
  1. function getJsonData(url) {  
  2.     //this function returns a promise that   
  3.     //gets data from the url supplied to it as a paramater  
  4.     return new Promise(function (fullfilled, reject) {  
  5.         $.get(url, function (data) {  
  6.             //on successful get, the fullfilled() is called and the data is sent as a parameter  
  7.             fullfilled(data);  
  8.         }).fail(function (error) {  
  9.             //on failure of get, the reject() is called and the error object can be sent as a parameter  
  10.             reject(error);  
  11.         });  
  12.     });  
  13. }  
  14. function filterCityByState(data) {  
  15.     //this function returns a promise that  
  16.     //filters data after an intrerval of 3 secs.  
  17.     return new Promise(function (fullfilled, reject) {  
  18.         setTimeout(function () {  
  19.             var filteredData = [];  
  20.             $.each(data, function (index, item) {  
  21.                 if (item.stateId == $('#ddlState').val()) {  
  22.                     filteredData.push(item);  
  23.                 }  
  24.             });  
  25.             //Once filtered, the fullfilled() is called and the filterd data is sent as a parameter  
  26.             fullfilled(filteredData);  
  27.         }, 3000);  
  28.     })  
  29. }  
  30.   
  31. $(document).ready(function () {  
  32.     getJsonData('/JSON/state.json').then(function (data) {  
  33.         $('#ddlState').itemTemplate({ dataSource: data });  
  34.     });  
  35.     $('#ddlState').change(function () {  
  36.         //Here we call the function getJsonData  
  37.         //as the function returns a promise one can use ".then()" and ".catch()"  
  38.         //the .then() is executed on the fulfillment/success of the promise  
  39.         //else the .catch() is executed  
  40.         //Now that the ".then()" to the getJsonData() returns another promise of the filter function  
  41.         //one can apply an additional ".then()" to the getJsonData()  
  42.         //which will be executed on the success of the filterCityByState()  
  43.         getJsonData('/JSON/city.json')  
  44.             .then(function (data) { return filterCityByState(data) }).catch(function (error) { alert('Error Occured'); })  
  45.             .then(function (filetereddata) { $('#ddlCity').itemTemplate({ dataSource: filetereddata }); });  
  46.     });  
  47. });  
So basically a Promise is like an event which is fired in response to fulfillment or rejection of a deferred function.
 
That's all for now.
 
Please do not forget to provide your valuable suggestions and feel free to ask queries.
 
That's all for this article, will see you in some other article. Until then,
 
Keep Learning... 
 
Read more articles on JavaScript: