Javascript is a synchronous programming language where instructions are blocked until the current task is completed. But there might be cases where we don't want the program execution to wait, like making an API(Application Programming Interface) call to fetch data. In these cases where asynchronous operations have to be performed, we use Callback, Promises, and async-await.
Before JavaScript promises were introduced, callbacks were used to perform asynchronous operations. But over the years, JavaScript promises replaced callback functions and are now considered the effective method to handle asynchronous operations.
This blog will cover the concept of JavaScript Promises in detail, along with some examples and frequently asked questions.
A Javascript promise is similar to a promise in real life. When we make a promise in real life, it guarantees that we will do something in the future. A promise has two possible outcomes: it will be kept when the time comes or won't. The same is true for promises in JavaScript. When a JavaScript promise is defined, it will be resolved when the time comes or rejected.
JavaScript promises are objects that represent the eventual completion or failure of an asynchronous operation. It is a means of assurance that a particular operation will occur shortly. Though, the promise doesn't need to be fulfilled every time. For example, if there is a network error, the promise won't be fulfilled.
A JavaScript Promise object contains both the producing code and calls to the consuming code. Let's have a look at the syntax of JavaScript Promises.
Syntax
let promise = new Promise(function (resolve, reject) {
// Producing code which may take some time
// Successful
resolve();
// Error
reject();
});
// Consuming code must wait for a fulfilled Promise
promise.then(
function (value) {
// Successful
},
function (error) {
// Error
}
);
When the above code is executed, a result is obtained which calls one of the two callback functions.
How JavaScript Promises Work
The JavaScript Promise object supports two properties: state and result. Let's have a look at them.
State
Description
Result
Pending
Initial state, i.e., before the promise succeeds or fails
undefined
Resolved
Completed promise
a value
Rejected
Failed promise
an error object
For example, if we request some data from the server using a Promise, it will be pending until the data is received. When we receive the data from the server successfully, the promise will be in the resolved state. If we don't receive any data, the promise will be in the rejected state.
If there are multiple requests, after the first promise is resolved or rejected, a new process is attached to it directly. This is called chaining, which will be discussed in the latter part of this blog.
Representation of the process of Promises
Creating a JavaScript Promise
Let's create our first JavaScript Promise. To create a Promise object, we make use of a constructor. It takes two parameters, one for the success case(resolve) and the other for the failure case(reject). Then we use the if-else statement to specify what to do in the success and failure case. If the given condition is met, the promise will be resolved. Otherwise, it will be rejected.
Code
// Creating a promise
const promise = new Promise((resolve, reject) => {
let promiseKept = true;
// Promise successful
if (promiseKept) {
const yesParty = "Gave friends a party!!!";
resolve(yesParty);
}
// Promise failed
else {
const noParty = "Didn't give friends a party!!!";
reject(noParty);
}
});
Consuming a JavaScript Promise
Now let's use the promise we have created. If you revisit the image at the beginning of this blog, you'll see two cases: resolved and rejected. If the promise is resolved, the .then() method is called. Else if the promise is rejected, it will jump to the catch( ) method.
Let's execute the above code by calling the checkIfPartyGiven() function.
Code:
checkIfPartyGiven();
Output:
Gave friends party!!!
As the above promise is resolved the following message is obtained.
JavaScript Promise Chaining
If there are multiple asynchronous operations to be done and if we try to use Callbacks for them, we'll find ourselves inside a situation called the Callback hell. This situation is solved using promise chaining.
Before going to promise chaining, let's look how a callback hell would look like.
As you can see, the above code is difficult to read and understand. Also, handling errors in the case of callbacks can be challenging. To overcome this issue, we make use of the promises.
Let's see how the above code would look using promises.
The code becomes much simplified in promises. This is because we are attaching callbacks rather than passing them. Now the code looks cleaner and easier to understand.
"JavaScript promises can save you from the callback hell."
Promise chaining is used in many scenarios in the real world. For example, it is used to fetch resources from an API. The resources are fetched, and a chain of promises is created to execute when the resource is fetched.
JavaScript Promises Method
Some of the frequently used promises methods are as follows:-
Method
Description
all(iterable)
It waits for all promises to be resolved or any one of them to be rejected.
allSettled(iterable)
It waits until all promises are either resolved or rejected.
any(iterable)
It returns the promise value as soon as any one of the promises is fulfilled.
race(iterable)
It waits until any one of the promises is rejected or resolved.
reject(reason)
It returns a new Promise object that is rejected for the given reason.
resolve(value)
It returns a new Promise object that is resolved with the given value.
finally()
It returns a promise when a promise is either fulfilled or rejected.
Frequently Asked Questions
What is the difference between Callbacks and JavaScript Promises?
Ans:- A Callback is a function that is called inside another function. It may or may not be performed asynchronously. A Promise is an object which takes a callback and executes it asynchronously.
2. What is async-await?
Ans:- async-await is syntactic sugar over JavaScript promises. async makes a function return a JavaScript Promise, and await makes a function wait for a JavaScript Promise.
3. What is meant by synchronous and asynchronous code in JavaScript?
Ans:- The code is synchronous when it blocks further execution of the remaining code until it finishes the current one. In contrast, asynchronous code allows the program to be executed immediately.
4. Which one is better, promise or callback?
Ans:- A promise is better than a callback as a promise is more readable, easier to use, and maintain than callbacks.
5. What is meant by a callback hell?
Ans:- The Callback hell/ Pyramid of Doom is when every callback takes an argument resulting from the previous callbacks. Here, the code structure looks like a pyramid, making it difficult to read and debug. If there is an error in one function, then all other functions get affected.
Key Takeaways
This blog covered the basic concepts of Javascriptpromises, along with some examples and frequently asked questions.