Hello everyone,
I'm trying to get a solid understanding of JavaScript Promises. I know they are used for asynchronous operations, but I'm finding it a bit tricky to grasp how they work under the hood and when exactly to use them. I've seen examples with `fetch`, but I'm curious about custom promise creation and handling different states (pending, fulfilled, rejected).
What are Promises?
A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It's a placeholder for a value that is not necessarily known when the Promise is created.
Promise States
- Pending: Initial state, neither fulfilled nor rejected.
- Fulfilled: The operation completed successfully, and the Promise has a resulting value.
- Rejected: The operation failed, and the Promise has a reason for the failure (an error).
Creating a Custom Promise
Here's a basic example of how to create a Promise:
function delay(ms) {
return new Promise((resolve, reject) => {
if (ms < 0) {
reject(new Error('Delay time cannot be negative'));
} else {
setTimeout(() => {
resolve(`Operation completed after ${ms}ms`);
}, ms);
}
});
}
// Example usage:
delay(2000)
.then((message) => {
console.log(message); // "Operation completed after 2000ms"
})
.catch((error) => {
console.error('Error:', error.message);
});
delay(-100)
.then((message) => {
console.log(message);
})
.catch((error) => {
console.error('Error:', error.message); // "Error: Delay time cannot be negative"
});
Chaining Promises
Promises can be chained together using `.then()` to handle sequential asynchronous operations.
fetch('/api/data/user/1')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(userData => {
console.log('User data:', userData);
return fetch(`/api/data/posts/${userData.id}`);
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(postData => {
console.log('User posts:', postData);
})
.catch(error => {
console.error('Fetching data failed:', error);
});
Async/Await
The async
and await
keywords provide a more modern and readable way to work with Promises.
async function getUserAndPosts(userId) {
try {
const userResponse = await fetch(`/api/data/user/${userId}`);
if (!userResponse.ok) {
throw new Error(`HTTP error! status: ${userResponse.status}`);
}
const userData = await userResponse.json();
console.log('User data:', userData);
const postsResponse = await fetch(`/api/data/posts/${userData.id}`);
if (!postsResponse.ok) {
throw new Error(`HTTP error! status: ${postsResponse.status}`);
}
const postData = await postsResponse.json();
console.log('User posts:', postData);
} catch (error) {
console.error('Fetching data failed:', error);
}
}
getUserAndPosts(1);
Any tips or common pitfalls I should be aware of when working with Promises?