Callum Slater

Callum Slater

1572677247

An in-depth understanding of JavaScript Promises

Promises are an important concept that is essential for a JavaScript developer to understand. If this concept is clear, the developer can utilize promises in a variety of ways in their day-to-day lives.

There are a lot of articles and tutorials available on the web about promises. However, very few of them act as a comprehensive guide to make use of promises. In this article, I will try to elaborate on promises in-depth, so you won’t need to go through other resources.

What Is a Promise?

As per MDN documentation: A promise is an object that represents the eventual completion or failure of an asynchronous operation, and it’s resulting value.

Promise Use Cases

Generally speaking, JavaScript is a scripting language that is synchronous in nature. In order to perform asynchronous operations, promises are of great help. Before promises were invented, when dealing with multiple asynchronous tasks, callbacks were used a lot.

But, multiple callback functions lead to unmanageable code that produced something known as callback hell. To solve this issue, promises are used.

That’s a lot of technical jargon, right! But, I think you would understand promises better if the discussion goes in a non-technical approach.

How Promises Work

You can think of JavaScript promises similar to promises you make in real life. Imagine you made a promise to your girlfriend that you will buy her an expensive gift. You don’t know whether you will be able to keep your promise. Maybe you will be able to keep your promise or maybe not.

So, if you promised but still didn’t manage to purchase the gift, the promise is in a pending state. If you are able to keep your promise, then your promise is fulfilled. But, if for some reason, you are unable to do so, your promise is in the rejected state.

When Were Promises Introduced in Javascript?

Promises aren’t a brand-new concept. In fact, they have been around since 1976, when the term was first introduced. At the start of 2011, Promises were popularized by jQuery deferred objects. The concept of deferred objects is similar to promises, but they do not follow the exact technical specification, as stated in the ECMA script 2015 for promises.

Finally, promises were officially added in the ECMA script 2015 specification and have also been implemented in all of the latest browsers and in Node Js.

Different States in a Promise

The same concepts apply to promises as well. A promise has any one of the following states. These are as follows:

  1. Pending: The task relating to the promise hasn’t fulfilled or rejected yet.
  2. Fulfilled: The task relating to the promise succeeded.
  3. Rejected: The task relating to the promise failed.

One important point to note here is that the function that creates the promise is able to keep track of the promise states.

Promises as Objects

var isPossibleToPurchaseGift = true;
var giftPromise = new Promise(function(resolve, reject) {
  if(isPossibleToPurchaseGift) {
     resolve('You are able to keep your promise');
  } else {
     reject('You are unable to keep your promise');
  }
});
console.log(giftPromise);

In the code above, we created a promise. If the value of variable the isPossibleToPurchaseGift is set to true, then the promise is resolved. Finally, we are displaying that promise’s resolved state in the browser’s console window.

If we look closer in the console window, we are able to expand the Promise object, then if we expand the highlighted portion as shown in the screenshot below, we are able to get the same as shown in the screenshot below.

Viewing promise in console

If we expand further, we will see something similar, as shown below. Note the highlighted portions in the image.

Viewing promise in console

Static Methods for Promises

  • Promise.all(promises): It waits for all promises to resolve and returns the array of all the results of the promises. An important point to note here is that if any of the promises are not fulfilled, then that becomes the error of the Promise.all and all other results are ignored.
  • Promise.allSettled(promises): It is a recently added method. Its purpose is to wait for all promises to settle and return their results as an array of objects with the state (that could be either ‘fulfilled’ or ‘rejected’) and value (if fulfilled) or reason (if rejected).
  • Promise.race(promises): It waits for the first promise to resolve and its outcome or error becomes the result.
  • Promise.resolve(value): It produces a resolved promise with the given value.
  • Promise.reject(error): It generates a rejected promise with the given error.

Creating a Promise

var isPossibleToPurchaseGift = true;

var willGetNewGift = new Promise(function(resolve, reject) {
    if(isPossibleToPurchaseGift) {
      var gift = {
         ring: true,
         flowers: true
      };
       resolve(gift);
    } else {
       var error = new Error('Left my wallet!!');
       reject(error);
    }
});

In the code above, we have created a promise called willGetNewGift. The promise constructor takes two parameters — the first is a resolve function, and the second one is a reject function.

Promise Resolve

In simple words, the resolve function indicates if the promise has succeeded, and then returns the resolved value from the promise. So, in the above code snippet, if the willGetNewGift variable is set to true, then the promise will return a gift object.

Promise Reject

The reject function returns a promise object that is rejected with an error message. In the above code snippet, if the willGetNewGift variable is set to false, then this promise will return an error object.

Invoking Promises

var getNewGift = function() {
  willGetNewGift
    .then(function(gift) {
    console.log(gift);

  })
  .catch(function(error) {
    console.log(error.message);
  });
}; 

getNewGift();

In the code above, we are calling the promise named “willGetNewGift” and then in order to get the value of the fulfilled promise we are using then() function. We set the variable "isPossibleToPurchaseGift " to true. If the value is true we are considering that the promise is resolved. So, we are able to display the gift object inside then() function. The complete code is shown below.

var isPossibleToPurchaseGift = false;
var willGetNewGift = new Promise(function(resolve, reject) {
  if(isPossibleToPurchaseGift) {
    var gift = {
      ring: true,
      flowers: true
    };
    resolve(gift);
  } else {
    var error = new Error('Left my wallet!!');
    reject(error);
  }
});

var getNewGift = function() {
  willGetNewGift
    .then(function(gift) {
      console.log(gift);
    })
    .catch(function(error) {
      console.log(error.message);
    });
};

getNewGift();

Chaining Promises in Javascript

Non-Technical Point of View

Let’s assume that, after making a promise to your significant other to buy her an expensive gift, you would also like to attend dinner with them. Additionally, you’d also love to go on a long drive with her. Imagine, the situation here, after keeping your first promise, you will have to keep your second and third promise too.

To handle these kinds of situations, you would need to chain multiple promises together. So promise chaining comes handy in these situations.

Technical Point of View

  1. A promise object is capable of performing asynchronous tasks in JavaScript. Each asynchronous task will return a promise object, and each promise object will have a then function that can take two parameters, a success handler, and an error handler.
  2. The then function will also return a promise, so that it is possible to chain multiple promises.
  3. Each of the handlers (success or error) can also return a value, which will be passed to the next function as a parameter in the chain of promises.
  4. If a handler returns a promise, then the next handler will be called only after that request is finished.

Let’s justify what we said earlier with an example.

Implementing Promise Chaining

var isPossibleToPurchaseGift = true;

var willGetNewGift = new Promise(function(resolve, reject) {
    if(isPossibleToPurchaseGift) {
      var gift = {
         ring: true,
         flowers: true
      };
       resolve(gift);
    } else {
       var error = new Error('Left my wallet!!');
       reject(error);
    }
});

var willAttendDinner = function(expensiveGift) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your promise by giving her an expensive ring';
    resolve(message);
  });
};

var willGoOnALongDrive = function(dinnerAttended) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your last promise by going on a long drive!';
    resolve(message);
  });
};

var getNewGift = function() {
  willGetNewGift
    .then(willAttendDinner)
    .then(willGoOnALongDrive)
    .then(function(longDrive) {
    console.log(longDrive);
  });
};

getNewGift();

In the above code snippet, we defined three separate functions — the first function, willGetNewGift returns a promise object, and the other functions also return promises.

Let me explain how this code runs. At first, the willGetNewGift function is called and returns a promise. Then, that promise object is passed to the next function, willAttendDinner. Similarly, it also returns a promise object.

Again, that object is passed to the willGoOnALongDrive function. Finally, the result of the function is displayed on the console. That’s why you will be able to see the message, “You kept your last promise by going on a long drive!

What the Heck is Promise.all()?

In simple words, promise.all() is a method that is beneficial when we have multiple promises, and we have to wait for each individual promise to complete before the next promise can be executed.

As per MDN documentation: The Promise.all() method returns a single Promise that resolves when all of the promises passed as an iterable have resolved or when the iterable contains no promises. It rejects with the reason of the first promise that rejects.

So, one fact is clear from the documentation: if any one of the promise objects in the array gets rejected, the entire Promise.all() method gets rejected.

How Does Promise.all() Work?

From the MDN docs, we know that the Promise.all() method takes an iterable object. By iterable object, it means that the object can be iterated easily. String and arrays are examples of such kind of iterable objects.

Generally, this method returns a pending promise object that gets resolved or rejected in an asynchronously as soon as the promise in the given iterable object has been resolved or rejected.

After promise is resolved successfully, the values of the respective promises will be there in the same order at the time they are passed in the promise all method. If any of the promises in the iterable gets rejected, all the promises get rejected.

Implementing Promise.all()

var isPossibleToPurchaseGift = true;
var willGetNewGift = function() {
   return new Promise(function(resolve, reject) {
    if(isPossibleToPurchaseGift) {
      var gift = {
         ring: true,
         flowers: true
      };
       resolve('You bought an expensive ring and flowers');
    } else {
       var error = new Error('Left my wallet!!');
       reject(error);
    }
  });
};
var willAttendDinner = function(expensiveGift) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your promise';
    resolve(message);
  });
};
var willGoOnALongDrive = function(dinnerAttended) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your last promise by going on a long drive!';
    resolve(message);
  });
};
var getNewGift = function() {
  Promise.all([
    willGetNewGift(),
    willAttendDinner(),
    willGoOnALongDrive()
  ]).then(function(result) {
    console.log(result);
  });
};
getNewGift();

In the above code snippet, we created 3 functions each of them returns a promise object. Then we called each of them in Promise.all() function, which returned the result of the promises inside an array. The output of this is shown below.

Final output from promise.all() function

If any one of the promise fails to resolve, the result will generate an error. The code snippet is shown below.

var isPossibleToPurchaseGift = false;
var willGetNewGift = function() {
   return new Promise(function(resolve, reject) {
    if(isPossibleToPurchaseGift) {
      var gift = {
         ring: true,
         flowers: true
      };
       resolve('You bought an expensive ring and flowers');
    } else {
       var error = new Error('Left my wallet!!');
       reject(error);
    }
  });
};
var willAttendDinner = function(expensiveGift) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your promise';
    resolve(message);
  });
};
var willGoOnALongDrive = function(dinnerAttended) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your last promise by going on a long drive!';
    resolve(message);
  });
};
var getNewGift = function() {
  Promise.all([
    willGetNewGift(),
    willAttendDinner(),
    willGoOnALongDrive()
  ]).then(function(result) {
    console.log(result);
  }).catch(function(error){
    console.log(error.message);
  });
};
getNewGift();

The output of the code is shown below.

Javascript promise all second output

What is Promise.race()?

If we need to return the result of the first resolved promise or rejected promise as soon as it is available, then we should use this function.

As per MDN documentation, The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.

Implementing Promise.race() in Javascript

var isPossibleToPurchaseGift = true;
var willGetNewGift = function() {
   return new Promise(function(resolve, reject) {
    if(isPossibleToPurchaseGift) {
      var gift = {
         ring: true,
         flowers: true
      };
      setTimeout(function(){
       resolve('You bought an expensive ring and flowers'); 
      }, 500);

    } else {
       var error = new Error('Left my wallet!!');
       reject(error);
    }
  });
};
var willAttendDinner = function(expensiveGift) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your promise';
     setTimeout(function(){
        resolve(message);
     }, 2000);
  });
};
var willGoOnALongDrive = function(dinnerAttended) {
  return new Promise(function(resolve, reject) {
    var message = 'You kept your last promise by going on a long drive!';
    setTimeout(function(){
       resolve(message);
    },3000);
  });
};
var getNewGift = function() {
  Promise.race([
    willGetNewGift(),
    willAttendDinner(),
    willGoOnALongDrive()
  ]).then(function(result) {
    console.log(result);
  }).catch(function(error){
    console.log(error.message);
  });
};
getNewGift();

In the above code snippet, we can see that from the 3 functions that return promise objects upon successful execution, only willGetNewGift() function took 500 milliseconds to execute. So the result of this promise is returned after running this code block.

Javascript promise race output

Are Javascript Promises Synchronous or Asynchronous?

At first, you should know that javascript is a single-threaded scripting language. Single-threaded means that it must execute one block of code before moving to execute the next code block. In simple words, the javascript code is always blocking in nature.

Sometimes we need to perform some tasks, and we are not sure exactly when that task will be complete and its result will be returned. But, at the same time, we need to guarantee that some blocks of code must be executed when we get a successful result or if a failure occurs we need to handle that scenario too.

To tackle these situations, we need to write asynchronous codes in javascript. Promises allow writing codes in an asynchronous way. So, obviously, we can say that promises are asynchronous.

Let’s justify with an example that promises are asynchronous.

var isPossibleToPurchaseGift = true;

// willGetNewGift promise definition

// willAttendDinner promise definition

// willGoOnALongDrive promise definition

var getNewGift = function() {
  console.log('Before giving gift');
  willGetNewGift
    .then(willAttendDinner)
    .then(willGoOnALongDrive)
    .then(function(longDrive) {
    console.log(longDrive);
  });
   console.log('After giving gift');
};

// call our promise
getNewGift();

Probably, you expected the following output.

Before giving gift
You kept your last promise by going on a long drive!
After giving gift

But, the actual output is shown in the screenshot below.

Final output from using promise.all()

Implementing Javascript Promises in Cleaner Way

All the examples in this article use the syntax of promise wrapper. We used this syntax so that you can understand promises easily, but practically we can write promises in a lot of better ways. If we write promises in that approach, maintaining promises for complex tasks will be a lot easier.

Let me explain what I mean by promise wrapper. In promise wrapper, you write codes that resolve or reject a promise depending on whether a promise successfully executed or not.

return new Promise(function(resolve, reject){
      // codes to execute
});

The above code snippet is an example of a promise wrapper. The following code snippet explains how you can write promises in a better way.

var isPossibleToPurchaseGift = true;
//var isPossibleToPurchaseGift = false;
var willGetNewGift = function() {
    if(isPossibleToPurchaseGift) {
       return Promise.resolve('It is possible to purchase gift');
    } else {
       var error = new Error('Left my wallet!!');
       return Promise.reject(error);
    }
};

var willAttendDinner = function(purchasedGift) {
//   purchasedGift = false;
  if(purchasedGift) {
    return Promise.resolve('It is possible to attend dinner');
  } else {
    return Promise.reject(new Error('Unable to attend dinner!!'));
  }

};

var willGoOnALongDrive = function(attendedDinner) {
//   attendedDinner = false;
  if(attendedDinner) {
    return Promise.resolve('It is possible to go on a long drive');
  } else {
    return Promise.reject(new Error('Unable to go on a long drive!!'));
  }

};

willGetNewGift()
  .then(willAttendDinner)
  .then(willGoOnALongDrive)
  .then(function(response){
  console.log(response);
}).catch(function(error){
  console.log(error.message);
});

Try uncommenting each of the commented statements one at a time, then run the codes again. I am sure you will understand the differences pretty easily.

Writing Javascript Promises With ES6/ES2015, ES7

ES6 or ES2015 introduced “let”, “const” and “fat arrow” syntax. Using that you can write promises in a better way. We can rewrite the previous example in a better way with ES6. The code snippet is shown below.

const isPossibleToPurchaseGift = true;
// const isPossibleToPurchaseGift = false;
var willGetNewGift = ()=> {
    if(isPossibleToPurchaseGift) {
       return Promise.resolve('It is possible to purchase gift');
    } else {
       const error = new Error('Left my wallet!!');
       return Promise.reject(error);
    }
};

var willAttendDinner = (purchasedGift)=> {
//   purchasedGift = false;
  if(purchasedGift) {
    return Promise.resolve('It is possible to attend dinner');
  } else {
    return Promise.reject(new Error('Unable to attend dinner!!'));
  }

};

var willGoOnALongDrive = (attendedDinner) => {
//   attendedDinner = false;
  if(attendedDinner) {
    return Promise.resolve('It is possible to go on a long drive');
  } else {
    return Promise.reject(new Error('Unable to go on a long drive!!'));
  }

};

willGetNewGift()
  .then(willAttendDinner)
  .then(willGoOnALongDrive)
  .then(response =>console.log(response))
  .catch(error =>console.log(error.message));

You can play around the code snippet better if you uncomment the commented lines.

ES7 introduced async and await syntax. After applying this to our ES6 code it would be easier for us to understand. Also, we don’t need to use then and catch functions. For error handling you need to use try…catch syntax of javascript.

const isPossibleToPurchaseGift = true;
// const isPossibleToPurchaseGift = false;
var willGetNewGift = ()=> {
    if(isPossibleToPurchaseGift) {
       return Promise.resolve('It is possible to purchase gift');
    } else {
       const error = new Error('Left my wallet!!');
       return Promise.reject(error);
    }
};

var willAttendDinner = (purchasedGift)=> {
  // purchasedGift = false;
  if(purchasedGift) {
    return Promise.resolve('It is possible to attend dinner');
  } else {
    return Promise.reject(new Error('Unable to attend dinner!!'));
  }

};

var willGoOnALongDrive = (attendedDinner) => {
  // attendedDinner = false;
  if(attendedDinner) {
    return Promise.resolve('It is possible to go on a long drive');
  } else {
    return Promise.reject(new Error('Unable to go on a long drive!!'));
  }

};
async function callFunctions() {
  try {
    willGetGift = await willGetNewGift();
    attendDinner = await willAttendDinner(willGetGift);
    willGoOnALongDrive = await willGoOnALongDrive(attendDinner);
     console.log(willGoOnALongDrive); 

  } catch(error) {
    console.log(error.message);
  }
} 

callFunctions();

Again, to understand the code better I would advise you to uncomment the commented code one at a time.

Conclusion

I hope after reading this article you will have an in-depth understanding of JavaScript promises. If you find this article helpful, don’t forget to share it among others.
Thank you!

#JavaScript

What is GEEK

Buddha Community

An in-depth understanding of JavaScript Promises
Julie  Donnelly

Julie Donnelly

1602406920

JavaScript Promise: Methods Comparison

Introduction

Promises in JavaScript are used to handle asynchronous operations by keeping track of whether a certain event has happened. If that certain event has taken place, it determines what happens next. Promises return a value which is either a resolved value or a reason why it’s rejected. They can handle multiple asynchronous operations easily and they provide better error handling than callbacks and events.

Callback: A callback is a function that is passed into another function as an argument to be executed later.

Events: Events provide a dynamic interface to a WebPage and are connected to elements in the Document Object Model(DOM), for example: onclick(), onmouseover() etc.

A Promise has four states

Pending: Before the event has happened, the promise is in the pending state.

Settled: Once the event has happened it is then in the settled state.

Fulfilled: Action related to the promise has succeeded.

Rejected: Action related to the promise has failed.

#javascript #javascript-development #javascript-tutorial #promises #javascript-tips

Vue Tutorial

Vue Tutorial

1589255577

The essential JavaScript concepts that you should understand

As a JavaScript developer of any level, you need to understand its foundational concepts and some of the new ideas that help us developing code. In this article, we are going to review 16 basic concepts. So without further ado, let’s get to it.

#javascript-interview #javascript-development #javascript-fundamental #javascript #javascript-tips

Promise.allSettled() vs Promise.all()

Promise.allSetlled() is recently introduced in ECMA 2020.
Check out how it is different from Promise.all()

https://www.geekstutorialpoint.com/2020/05/promiseallsettled-vs-promiseall.html

#javascript #promise.all #promise.allsettled #ecma #promise #jquery

Rahul Jangid

1622207074

What is JavaScript - Stackfindover - Blog

Who invented JavaScript, how it works, as we have given information about Programming language in our previous article ( What is PHP ), but today we will talk about what is JavaScript, why JavaScript is used The Answers to all such questions and much other information about JavaScript, you are going to get here today. Hope this information will work for you.

Who invented JavaScript?

JavaScript language was invented by Brendan Eich in 1995. JavaScript is inspired by Java Programming Language. The first name of JavaScript was Mocha which was named by Marc Andreessen, Marc Andreessen is the founder of Netscape and in the same year Mocha was renamed LiveScript, and later in December 1995, it was renamed JavaScript which is still in trend.

What is JavaScript?

JavaScript is a client-side scripting language used with HTML (Hypertext Markup Language). JavaScript is an Interpreted / Oriented language called JS in programming language JavaScript code can be run on any normal web browser. To run the code of JavaScript, we have to enable JavaScript of Web Browser. But some web browsers already have JavaScript enabled.

Today almost all websites are using it as web technology, mind is that there is maximum scope in JavaScript in the coming time, so if you want to become a programmer, then you can be very beneficial to learn JavaScript.

JavaScript Hello World Program

In JavaScript, ‘document.write‘ is used to represent a string on a browser.

<script type="text/javascript">
	document.write("Hello World!");
</script>

How to comment JavaScript code?

  • For single line comment in JavaScript we have to use // (double slashes)
  • For multiple line comments we have to use / * – – * /
<script type="text/javascript">

//single line comment

/* document.write("Hello"); */

</script>

Advantages and Disadvantages of JavaScript

#javascript #javascript code #javascript hello world #what is javascript #who invented javascript

Hugo JS

Hugo JS

1599295469

What is Callback-Function in JavaScript? How it is Replaced By Promises?

Let us understand term _Callback _by an real-world example: Suppose, you are calling to your Girlfriend (If you have) and she is busy in another call then she send message to you : “I am busy right now, Call back you later.!!”. After completing her work, she calls you back and this is what call back in JavaScript as well.

In JavaScript, When a function is executing (Girlfriend is talking with someone) then after function execution is completed another function is started for execution this is call back function.

Now you are thinking that its depend upon when, where you are calling function and all function call is “Call-back function”. Image for post

Here, _printWorld() _function is executed after _printHello() _complete its execution but this is not call-back function example because _printHello() _is not Asynchronous function. Suppose, _printHello() _prints after 1 Second then _printWorld() _executes first.

Image for post

What if we want “Hello World” output when Asynchronous function is there. We can pass function as argument and calls it after _printHello() _complete its execution. Here below code snippet of how _function pass as argument _:

Image for post

Callback function can be defined as a function passed by argument and executes when one function completes its execution.

Suppose, If you have API (Application Programming Interface) to get Students Roll numbers and select one of Roll number — getting that roll number’s data and print that data. We don’t have API to get students data so we are using _setTimeout() _Async function and getting roll number after 2s, We are also selecting one of roll number manually after 2s and print Roll number’s data after 2s. This can be done by call back function.

Image for post

The program became complex and complex if we have too many things to do like Getting Students data, Selecting one of them student, get student’s roll number and get result by roll number then it become very complex. If you have any Error in this then debugging is also tedious task, this things is called “Callback Hell”, which is shape like “Pyramid Of Doom”.

To overcome with this problem, Promises is introduced in JavaScript. Promises has three states : Pending, Resolved, Reject. Promises is created by Constructor : new Promise(). It has one executor function which has two arguments (resolve, reject).

Promise object has three methods: then(), catch() & finally().

Image for post

If Promise is successfully executed then its data is transferred through resolve function and if it has error then passed through reject function.

We have implemented same task which is done using call back function in Promises and its easily understandable However it is complicated compare to callback function but when you use promises for sometimes then it’s easy to implement.

In _getRollNumber(), _resolve method’s data is caught by then() functions arguments and reject method’s data is caught by catch() function. Here In Promises, Every task has different promises because of that it is easy to debug and readable compare to call back function. You can see that there is no shape like “Pyramid of Doom” in Promises. This is how Callback function is replaced by Promises.

Thank you for reading!

This article was originally published on Medium.com

#javascript-tips #advanced-javascript #javascript #callback-function #promises