A JavaScript promise is an object which returns a value that we hope to receive in the future, but not at this moment.
Because of the way promises behave, they are used extensively in asynchronous programming. Let’s use an analogy to understand promises and see how they relate to real-world promises.
Suppose you make a promise to learn JavaScript in one month. At this moment you do not know whether you will be able to do it or not.
Your promise can be in the following three states:
Pending: Your one month is not completed yet, hence, you are not sure whether your promise will be fulfilled or not.
Fulfilled: You successfully finished learning JavaScript in one month.
Rejected: You failed in fulfilling the promise.
All promises start in the pending state and then end with either being fulfilled or rejected.
We use the promise constructor to create a promise in the following manner.
1
2
3
4
5
6
const learntJavascript = true;
const p = new Promise((resolve, reject) => {
if (learntJavascript)
resolve('Successfully Learnt javascript');
else reject('Could not learn Javascript');
})
Here p is a promise, which is declared using the promise constructor. This constructor accepts a function called the executor, and this executor function accepts two functions called resolve and reject.
We manually call the resolve or reject depending on whether the promise succeeded or failed.
Let’s execute the code.
Our promise was resolved. But as you might have noticed, this is not asynchronous code, which means our code is running with the flow of the program and not making us wait. This is why we see the output for the promise being resolved. But what if we introduce some delay?
Change your code in the following way to introduce a three-second delay.
1
2
3
4
5
6
7
8
const learntJavascript = true;
const p = new Promise((resolve, reject) => {
setTimeout(() => {
if (learntJavascript) resolve("Successfully Learnt javascript");
else reject("Could not learn Javascript");
}, 3 * 1000);
});
console.log(p);
Now let’s execute the file to see the result.
Our machine waits a little bit and gives this output, which honestly is a useless output. How will we know whether the promise was fulfilled or failed? We will see this later on, believe me, it’s a promise 😜. For now, let’s see what we have learned this far.
A promise can be created using the promise constructor and can have only three states which are pending, fulfilled, and rejected. A promise can go from pending to either fulfilled or rejected state.
The then()
method:
We can attach a then() method to a promise. This function is executed when the promise is resolved successfully. For instance, in the above example we can attach the then() method to the object p.
1
2
3
p.then((msg) => {
console.log(msg);
});
Now if we execute our code, we will see the following result. Although we will still have to wait for three seconds for our result.
The catch()
method:
Now make the variable learntJavascript false and run the code. You will see this weird error.
It says that the error was an unhandled promise rejection warning and originated because the rejection was not handled by a catch block. Let’s break down the error.
We told our program what to do when the promise is resolved but what about when the promise fails? For that, we use a catch block, which is similar to the then() block but is executed when the promise fails.
To use a catch block modify the code like this.
1
2
3
4
5
6
p.then(msg => {
console.log(msg);
})
.catch(err => {
console.log(err);
});
Now, if we run the code we see the following output.
The finally()
block:
What if there’s a block of code that you want to execute whether the promise succeeds or not? Using our above example, whether the user was successful in learning JavaScript in one month or not we still want to remind the user that one month has passed. To do that do the following.
1
2
3
4
5
6
7
p.then((msg) => {
console.log(msg);
})
.catch((err) => {
console.log(err);
})
.finally(() => console.log("One month has passed"));
Now let’s see the output for both the failure and success of the promise…
In the first output the promise failed and in the second it succeeded, but in both cases the finally() block was executed.
Whenever we want our code to wait for some specific task to execute before moving on then we can use these two keywords. Any instruction that is prefixed by await will stop the code’s execution until it is executed. The await keyword can only be used inside a function that is declared asynchronous using the async keyword.
Example.
1 2 3 4 5 6
const func = async () => { await asynchronousFunction(); synchronousFunction(); } func();
Here the await keyword will pause the execution of the code for the asynchronousFunction().
You can also read about error handling in one of my other articles here.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise