Published
Imagine you order something online. You pay for the item, and they 'promise' to deliver it to your location. You don't have exactly when it will come, but you are guaranteed it will arrive. JavaScript Promises are similar. They are objects that represent the eventual completion (or failure) of an asynchronous operation and its resulting value.
A Promise in JavaScript can be in one of three states: pending, fulfilled, or rejected. 'Pending' means the Promise is still working and hasn't completed yet. 'Fulfilled' means the Promise has successfully completed. 'Rejected' means an error occurred.
In JavaScript, you can create a Promise by using the 'new' keyword and the Promise constructor. This takes one argument, a function, which in turn takes two parameters: resolve and reject. 'Resolve' is a function call when the Promise completes successfully, carrying the result. 'Reject' is called if an error occurs, carrying the error.
const promise = new Promise((resolve, reject) => {
// Some asynchronous operation here
if (/* everything turned out fine */) {
resolve('Stuff worked!');
} else {
reject(Error('It broke'));
}
});
To use a Promise and get the result (or error), we can use '.then()' method for the success scenario, and '.catch()' for handling errors. These methods are also used for chaining Promises.
promise
.then((result) => console.log(result)) // This will run if the Promise is successful
.catch((error) => console.error(error)); // This will run if the Promise failed
Sometimes, operations are dependent on the result of a previous operation. If these operations are asynchronous, it can lead to 'callback hell' where callbacks are nested within callbacks making code hard to read and debug. Promise chaining is a technique to flatten the code and make it more readable and easier to understand.
// An example of Promise chaining
firstFunction()
.then((firstResult) => secondFunction(firstResult))
.then((secondResult) => thirdFunction(secondResult))
.catch((error) => console.error(error));
Promise.all is a method that takes an array of Promises and returns a new Promise that only fulfills when all of the promises in the array have been fulfilled, or rejects as soon as one of them rejects. The result of Promise.all is an array of results from all the promises.
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => console.log(values));
// expected output: Array [3, 42, 'foo']
By reading this article, you've invested 1.50 minutes of your life into expanding your knowledge and perspectives. Now, imagine learning on-the-go, turning every moment into an opportunity for growth and discovery.
Imagine you want a new toy. You ask your parents for it, and they might say 'Okay, we promise you'll get it for your birthday'. So now, you're waiting. Your birthday isn’t here yet, so you didn't get the toy, but you have a promise that you'll get it. That’s kind of what a promise is in JavaScript. It’s a way for JavaScript to keep track of some work that it promised to do, while it’s waiting for that work to finish.
A promise in JavaScript can be in one of three states. Imagine you are waiting for your birthday. The toy that you expect to get is like a promise. Here, the three states are:
This is like the time when you're waiting for your birthday to come. In this state, the promise is neither fulfilled nor rejected. The toy – or promise – is on its way, but it’s not here yet.
Yay! It’s your birthday and you got the toy! Your parents fulfilled their promise. Similarly, in JavaScript when the work that was promised is finished and everything went well, the promise is 'fulfilled'. This is the best case scenario.
Oh no, your parents couldn’t get the toy and your birthday is here. The promise they made to you is now 'rejected'. Similarly, in JavaScript if something went wrong and the promise could not be fulfilled, it gets 'rejected'. This means the work that was promised couldn’t be completed successfully.
With the toy promise your parents gave you, you were really expecting to get it on your birthday. You even made some plans - if the toy arrives, you play with it; if it doesn’t, you play with your old toys. In JavaScript, we do the exact same thing using '.then' for the case when we get our toy or the promise is fulfilled, and '.catch' for the case when we don't get our toy or the promise is rejected. This is called 'Handling Promises'.
let toyPromise = new Promise(function(resolved, rejected) { /* some code */ });
toyPromise.then(function(toy) { /* code to play with toy */ })
.catch(function(reason) { /* code to play with old toys */ });
Let’s say your parents promised you two toys now, one for your birthday and another for Christmas. Christmas is after your birthday, so the second promise depends on the first one. In JavaScript, we call this dependency as 'Chaining Promises'. After getting the first toy, you can start another promise for the Christmas toy! You can chain them together so you can handle them in order.
toyPromise.then(function(birthdayToy) { /* play with birthday toy */
return new Promise(function(resolved, rejected) { /* Christmas toy promise */ });})
.then(function(christmasToy) { /* play with Christmas toy */ })
.catch(function(reason) { /* handle any broken promises */ });
When you are waiting for your first promised toy, you can’t accept the second toy. You have to wait until it’s your birthday, get your birthday toy, then wait until Christmas to get your Christmas toy. In JavaScript, we can represent this waiting using keywords 'async' and 'await'. If your function needs to wait for a promise to complete, you add 'async' before the function and 'await' before the promise. This tells JavaScript to wait for the promise to finish before moving on to the next line of code.
async function waitAndPlayWithToys() {
let birthdayToy = await toyPromise;
/* play with birthday toy */
let christmasToy = await christmasPromise;
/* play with christmas toy */
}
By reading this article, you've invested 2.53 minutes of your life into expanding your knowledge and perspectives. Now, imagine learning on-the-go, turning every moment into an opportunity for growth and discovery.
To understand how Promises are used in real JavaScript coding, see Asynchronous JavaScript
About author
Roman Y.
Senior Software Engineer at Nike
Certain articles only distributed to subscribers through email