JavaScript promises are very essential . As a web developer we hardly have a way to avoid it. Even though you don't like promises your interviewers love them.
In, this blog I'll try to make promises easier for you
So without further ado, Lets get Started
What is a Promise?
A promise is a JavaScript object that allows you to make asynchronous(aka async) calls. It produces a value when the async operation completes successfully or produces an error if it doesn't complete.
There are two ways of looking at it:
- it is a placeholder or container for the final result that will eventually be delivered.
- it is an object with which we can register listeners.
You can create promise using the constructor method,
We need to pass a function to the Promise Constructor. That function is called the executor function. The executor function takes two arguments, resolve and reject. These two are callback functions for the executor to announce an outcome.
The resolve method indicates successful completion of the task, and the reject method indicates an error. You do not implement the resolve/reject method. JavaScript provides it to you. You need to call them from the executor function.
Let's try to understand it better by implementing Promise-based Function.
addAsync() immediately invokes the Promise constructor. The actual implementation of that function resides in the callback that is passed to that constructor i.e at line no 3. That callback is provided with two functions:
- resolve is used for delivering a result (in case of success).
- reject is used for delivering an error (in case of failure)
The Promise States And Object
A promise object is capable of informing the consumers when the execution has been started, resolved , or rejected.
A promise object has the following internal properties,
- State
- Result
State
State can have the following values,
- Pending: When the function starts.
- Fulfilled: When the promise is resolved successfully.
- Rejected: When the promise rejects.
A Promise can be in either one of three states: pending, fulfilled, or rejected. If a Promise is in a final (non-pending) state i.e it is either resolved or rejected, it is called settled.
Result
Result can have the following values,
- undefined: Initially, when the state value is pending.
- value: When the promise is resolved(value).
- error: When the promise is rejected.
Some Promises are never settled
It is possible that a Promise is never settled. For example: new Promise(() => {})
Handling The Promises By Consumer
The promise object returned by the new Promise constructor has it all. A consumer can use it to know the state(pending, fulfilled, or rejected) and the possible outcomes(value or error) from it.
But these are code-inaccessible, but they are inspectable. It means that we will be able to inspect the state and result property values using a debugger tool, but we will not be able to access them directly.
That's where three important handler methods, .then(), .catch(), and .finally() comes into picture. These methods help us create a link between the executor and the consumer when a promise resolves or rejects.
The .then() Method
We get a .then() method from every promise. The purpose of this method is to let the consumer have the access to the outcome of a promise. It accepts two functions as arguments, result and error.
If you are just interested in the successful outcome, you can chose to pass only one argument
or
if you are interested in only the error, pass null as the value for the first argument.
Using .then() method you can also perform the following exceptional things,
- can return another Promise
- can return undefined
- can throw an error
Using .then() method in a Promise-based function
When the last line executes, it console logs 5
OutPut: 5
The .catch() Method
You can use this handler method to handle errors (rejections) from promises. As we discussed already, we can also handle the error situation using .then() method but passing null makes the syntax look bit odd. So let us now handle the error situation using .catch() method.
Let try to understand it by the following example,
Will give the following output
- We use the reject method in the above code to reject the promise.
- You can pass any type of argument to the reject method like the resolve method.
- However, it is recommended to use the Error objects.
- We use the .catch() handler to handle the rejection. In the real world, you will have both .then() and .catch() methods to handle the resolve and reject scenarios.
Promises specialize in one-off results and protect us against race conditions (registering too early or too late):
- If we register a .then() callback or a .catch() callback too early, it is notified once a Promise is settled.
- Once a Promise is settled, the settlement value (result or error) is cached. Thus, if .then() or .catch() are called after the settlement, they receive the cached value.
The .finally() Method
The Promise method .finally() is often used as follows:
The .finally() callback is always executed – independently of somePromise and the values returned by .then() and/or .catch(). In contrast:
- The .then() callback is only executed if somePromise is fulfilled.
- The .catch() callback is only executed if:
- either somePromise is rejected,
- or the .then() callback returns a rejected Promise,
- or the .then() callback throws an exception.
Note that .finally() ignores what its callback returns and simply passes on the settlement that existed before it was called
That's all for now I hope I made JavaScript Promises easy for you.