Introduction
JavaScript promises are a powerful addition to language.
In web development, dealing with asynchronous operations is inevitable. Whether it’s fetching data from a server, reading files, or executing time-consuming computations, JavaScript developers often find themselves in scenarios where they need to handle tasks that don’t complete instantly.
This is where understanding JavaScript promises come into play.
In this blog post, we’ll delve deep into what JavaScript promises are and how to use them, accompanied by practical code examples.
What is a JavaScript Promise?
A Promise in JavaScript is an object representing the eventual completion (or failure) of an asynchronous operation. Essentially, it’s a placeholder for a value that will be available in the future.
Promises help you manage asynchronous operations more efficiently, allowing you to write cleaner, more readable, and maintainable code.
Promises have three states:
- Pending: The initial state of a promise. The operation has not completed yet.
- Fulfilled: The operation completed successfully.
- Rejected: The operation failed.
Creating a Promise
Let’s start with creating a basic promise.
const myPromise = new Promise((resolve, reject) => {
const condition = true;
if (condition) {
resolve('Promise is resolved successfully.');
} else {
reject('Promise is rejected.');
}
});
myPromise.then(result => console.log(result))
.catch(error => console.log(error));
In this example, myPromise
is a new Promise. It takes a function with two parameters: resolve
and reject
. If the condition is true
, the promise is resolved; otherwise, it’s rejected. The .then()
method is used to handle the fulfilled state, and .catch()
is for handling rejection.
Handling Asynchronous Operations
Promises really shine when handling asynchronous operations, such as API calls. Here’s an example using the Fetch API:
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Here, fetch()
returns a promise. We chain .then()
to handle the response, converting it to JSON, and then another .then()
to work with the actual data. .catch()
is used to handle any errors.
Chaining Promises
Promises can be chained, which is powerful for sequential asynchronous operations:
const cleanRoom = () => {
return new Promise((resolve, reject) => {
resolve('Cleaned The Room');
});
};
const removeGarbage = message => {
return new Promise((resolve, reject) => {
resolve(`${message} then removed the Garbage`);
});
};
const winIcecream = message => {
return new Promise((resolve, reject) => {
resolve(`${message} then won an icecream`);
});
};
cleanRoom()
.then(result => removeGarbage(result))
.then(result => winIcecream(result))
.then(result => console.log(`Finished: ${result}`));
In this example, each function returns a promise. After cleaning the room, the garbage is removed, and then the icecream is won, demonstrating a sequence of actions.
Error Handling in Promise Chains
Error handling in promise chains is crucial. If any promise in the chain is rejected, the control jumps to the nearest .catch()
:
cleanRoom()
.then(result => removeGarbage(result))
.then(result => winIcecream(result))
.then(result => console.log(`Finished: ${result}`))
.catch(error => console.log(`Error: ${error}`));
Here, if any of the promises gets rejected, the error will be caught and logged.
Promise.all
When you need to run multiple promises in parallel and wait for all of them to complete, Promise.all
is very useful:
Promise.all([cleanRoom(), removeGarbage(), winIcecream()])
.then(() => console.log("All tasks completed successfully"))
.catch(error => console.log(`Error in completing tasks: ${error}`));
In this case, Promise.all
takes an array of promises and returns a new promise that resolves when all the promises in the array are resolved.
Conclusion
Promises in JavaScript are a powerful tool for managing asynchronous operations, making your code cleaner and easier to maintain.
They allow you to handle operations that occur in the background and may take some time to complete, such as API requests or file operations.
By mastering promises, you can ensure your JavaScript applications are efficient, readable, and robust.
Remember, good error handling is essential to make your application resilient and reliable.
Some great documentation for JavaScript promises can be found here: – https://www.w3schools.com/js/js_promise.asp
I have a great post about the same technique with TypeScript here: – Understanding TypeScript Promises