๐ Day 11 of #30DaysOfJavaScript: Understanding Promises in JavaScript
Welcome to Day 11! Today, weโre diving into a fundamental concept in JavaScriptโs approach to handling asynchronous operations: Promises. If youโve ever been stumped by complex asynchronous code, understanding promises will be your gateway to more readable, efficient, and manageable JavaScript!
๐ What Are Promises?
In JavaScript, a promise is an object that represents the eventual completion (or failure) of an asynchronous operation. Think of it as a placeholder for a value we donโt yet have but will eventually. Promises allow us to handle operations that take time, like fetching data from an API or performing heavy calculations, without blocking the rest of the code.
A promise can be in one of three states:
Pending: The operation has not yet been completed in the initial state.
Fulfilled: The operation was successful, and a value is available.
Rejected: Operation failed, and an error reason is available.
๐ก Why Use Promises?
Promises help to avoid โcallback hell,โ where nested callbacks make code difficult to read and maintain. With promises, we get a cleaner syntax thatโs easier to manage, chain, and debug. Theyโre crucial for async tasks like network requests, timers, or reading files.
๐ How Promises Work: A Simple Example
Let's start with a basic example:
let myPromise = new Promise((resolve, reject) => {
let success = true;
setTimeout(() => {
if (success) {
resolve("Promise fulfilled!");
} else {
reject("Promise rejected!");
}
}, 2000);
});
myPromise
.then(result => {
console.log(result); // Output: "Promise fulfilled!"
})
.catch(error => {
console.error(error); // Output: "Promise rejected!"
});
Hereโs whatโs happening:
We create a new
Promise
and pass it a function with two arguments:resolve
andreject
.If the operation succeeds, we call
resolve()
with the value we want.If the operation fails, we call
reject()
with an error message.
๐ Practical Use Case: Fetching Data
Promises shine when we need to fetch data, such as from an API. Hereโs an example using the fetch()
function, which returns a promise:
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then(data => {
console.log(data); // Output: Post data as JSON object
})
.catch(error => {
console.error("There was a problem with the fetch operation:", error);
});
In this example:
fetch()
initiates a request and returns a promise.The
then()
block handles the successful response.If thereโs an error (e.g., the server is unreachable), the
catch()
block handles it.
๐ Promise Chaining
You can chain multiple .then()
calls to sequence-dependent asynchronous operations:
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => response.json())
.then(user => {
console.log("User found:", user);
return fetch(`https://jsonplaceholder.typicode.com/posts?userId=${user.id}`);
})
.then(response => response.json())
.then(posts => {
console.log("User's posts:", posts);
})
.catch(error => {
console.error("Error:", error);
});
This example fetches a user and then uses their ID to fetch their posts. Each
.then()
handles the result of the previous operation, creating a logical flow of actions.
โ
Error Handling with .catch()
Promises simplify error handling. Instead of handling errors at every step, we can use .catch()
at the end of the chain to catch any errors from any preceding step:
fetch('https://jsonplaceholder.typicode.com/invalid-endpoint')
.then(response => response.json())
.catch(error => {
console.error("Caught error:", error);
});
๐ ๏ธ Practical Tips for Working with Promises
Always handle rejections: Unhandled promise rejections can lead to bugs and unpredictable behavior.
Keep promises in scope: Chained
.then()
calls work well when each promise depends on the previous one.Use
Promise.all()
for multiple promises: If you have multiple asynchronous tasks that can run concurrently,Promise.all()
lets you wait for all of them to complete.
Example with Promise.all()
:
const fetchUser = fetch('https://jsonplaceholder.typicode.com/users/1');
const fetchPosts = fetch('https://jsonplaceholder.typicode.com/posts?userId=1');
Promise.all([fetchUser, fetchPosts])
.then(responses => Promise.all(responses.map(response => response.json())))
.then(data => {
console.log("User:", data[0]);
console.log("Posts:", data[1]);
})
.catch(error => {
console.error("Error with fetching data:", error);
});
๐ Wrapping Up
Promises are powerful tools for handling asynchronous tasks in JavaScript, making your code cleaner and more manageable. Mastering promises not only enhances your JavaScript skills but also prepares you for understanding async/await, which builds on promises for even more readable code.
๐น Additional Video Resources
To further clarify JavaScript promises, here are some helpful videos. They offer quick, in-depth explanations of promises, with practical examples for both beginners and advanced users.
JavaScript Promises in 10 Minutes by Web Dev Simplified
This 10-minute tutorial explains the essentials of promises, from basic concepts to practical uses.Understanding JavaScript Promises: A Beginner's Guide
A step-by-step breakdown for newcomers, ideal for anyone looking to start working with promises.JavaScript Promises Crash Course by Academind
This crash course dives deeper, covering error handling, chaining, and real-world examples.
Stay tuned for tomorrowโs lesson as we explore async/await and see how it complements promises to make async programming even smoother. Happy coding!
Subscribe to my newsletter
Read articles from Stanley Owarieta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Stanley Owarieta
Stanley Owarieta
๐๐๐ฝ๐ถ๐ฟ๐ถ๐ป๐ด ๐๐ฟ๐ผ๐ป๐๐ฒ๐ป๐ฑ ๐๐ฒ๐๐ฒ๐น๐ผ๐ฝ๐ฒ๐ฟ passionate about ๐ ๐๐ซ๐๐๐๐ง๐๐ฅ๐ฉ, ๐๐ค๐๐๐ฃ๐, ๐๐ฃ๐ ๐๐ช๐๐ก๐๐๐ฃ๐ ๐ข๐ฎ ๐๐ช๐ฉ๐ช๐ง๐ ๐๐ฃ ๐ฉ๐๐๐. Along with my ๐ก๐ค๐ซ๐ for ๐๐๐จ๐๐๐ค๐ฃ, ๐๐๐ข๐๐ฃ๐, ๐๐ฃ๐ ๐ก๐ช๐ญ๐ช๐ง๐ฎ ๐ก๐๐ซ๐๐ฃ๐, I have big dreams like ๐ค๐ฌ๐ฃ๐๐ฃ๐ ๐ ๐ฅ๐ง๐๐ซ๐๐ฉ๐ ๐๐๐ฉ and ๐ก๐๐ซ๐๐ฃ๐ ๐๐ฃ ๐ ๐ก๐ช๐ญ๐ช๐ง๐ฎ ๐๐ค๐ข๐ ๐ค๐ฃ๐ ๐๐๐ฎ. Since 2021, Iโve invested in ๐๐ฝ๐ฝ๐น๐ฒ, ๐๐บ๐ฎ๐๐ผ๐ป, ๐ฆ๐ต๐ผ๐ฝ๐ถ๐ณ๐, ๐ฎ๐ป๐ฑ ๐๐ผ๐ผ๐ด๐น๐ฒโworking toward financial independence. I also look forward to being a ๐น๐ผ๐๐ถ๐ป๐ด ๐ณ๐ฎ๐๐ต๐ฒ๐ฟ ๐ฎ๐ป๐ฑ ๐ฎ ๐ฑ๐ฒ๐๐ผ๐๐ฒ๐ฑ ๐ฝ๐ฎ๐ฟ๐๐ป๐ฒ๐ฟ, growing a ๐บ๐ถ๐น๐น๐ถ๐ผ๐ป-๐ฑ๐ผ๐น๐น๐ฎ๐ฟ ๐ฏ๐ฟ๐ฎ๐ป๐ฑ together with my ๐ณ๐๐๐๐ฟ๐ฒ ๐๐ถ๐ณ๐ฒ. Letโs connect and inspire each other on this journey!