JavaScript Promise then()
Method: Handling Fulfillment
The then()
method is a fundamental part of the JavaScript Promise API, used to handle the fulfillment (successful resolution) of a Promise. It allows you to specify what should happen when the Promise completes successfully. This guide will explore the then()
method in detail, providing clear examples and best practices to effectively manage asynchronous operations in JavaScript.
What is the then()
Method?
The then()
method is called on a Promise object and takes up to two arguments:
onFulfilled
: A callback function that is executed when the Promise is resolved. It receives the resolved value as its argument.onRejected
(optional): A callback function that is executed when the Promise is rejected. It receives the rejection reason as its argument. It is generally better to use.catch()
for handling rejections, as.catch()
is more readable.
The then()
method returns a new Promise, which allows for chaining multiple asynchronous operations.
Syntax
promise.then(onFulfilled, onRejected);
Parameters
Parameter | Type | Description |
---|---|---|
onFulfilled |
Function | A callback function called when the Promise is resolved. It receives the resolved value as an argument. |
onRejected (optional) |
Function | A callback function called when the Promise is rejected. It receives the rejection reason as an argument. It’s generally better to use .catch() for handling rejections. |
Return Value
A new Promise
object. This allows for chaining multiple then()
calls, creating a sequence of asynchronous operations. π
Basic Example: Handling Promise Resolution
This example demonstrates a simple Promise that resolves after a delay. The then()
method is used to handle the resolved value.
const promiseThenBasic = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Promise resolved successfully!");
}, 1000);
});
promiseThenBasic.then(
(value) => {
console.log(value); // Output: Promise resolved successfully! (after 1 second)
},
(error) => {
console.error("Error:", error);
}
);
Output:
Promise resolved successfully!
Chaining then()
Methods
The then()
method returns a new Promise, enabling chaining. Each then()
receives the result of the previous one.
const promiseThenChain = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 500);
});
promiseThenChain
.then((value) => {
console.log("First then:", value); // Output: First then: 10
return value * 2;
})
.then((value) => {
console.log("Second then:", value); // Output: Second then: 20
return value + 5;
})
.then((value) => {
console.log("Third then:", value); // Output: Third then: 25
});
Output:
First then: 10
Second then: 20
Third then: 25
Returning Promises from then()
Returning a Promise from the onFulfilled
callback allows you to chain asynchronous operations sequentially.
const promiseThenReturn = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("First Promise");
}, 500);
});
promiseThenReturn
.then((value) => {
console.log(value); // Output: First Promise
return new Promise((resolve) => {
setTimeout(() => {
resolve("Second Promise");
}, 500);
});
})
.then((value) => {
console.log(value); // Output: Second Promise (after 0.5 second)
});
Output:
First Promise
Second Promise
Handling Errors with then()
and catch()
While then()
can handle rejections with its second argument, itβs cleaner to use catch()
for error handling.
const promiseThenError = new Promise((resolve, reject) => {
setTimeout(() => {
reject("Promise rejected!");
}, 500);
});
promiseThenError
.then(
(value) => {
console.log(value); // This won't be executed
}
)
.catch((error) => {
console.error("Error:", error); // Output: Error: Promise rejected!
});
Output:
Error: Promise rejected!
Real-World Example: Fetching Data
Here’s a real-world example of using then()
with the Fetch API to retrieve data from an API:
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
fetch(apiUrl)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then((data) => {
console.log("Data fetched:", data);
})
.catch((error) => {
console.error("Fetch error:", error);
});
This example fetches data from a mock API, parses the JSON response, and logs the data. It also includes error handling using catch()
. π
Note: Always include error handling in your Promise chains to gracefully manage rejections. β οΈ
Advanced Example: Asynchronous Operations in Sequence
This advanced example showcases performing a series of asynchronous operations in sequence using then()
chaining. It simulates fetching user data, then fetching posts for that user, and finally processing the posts.
function fetchUserData(userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ userId: userId, name: "John Doe" });
}, 500);
});
}
function fetchUserPosts(userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{ postId: 1, title: "First Post" },
{ postId: 2, title: "Second Post" },
]);
}, 500);
});
}
function processPosts(posts) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(posts.map((post) => post.title));
}, 500);
});
}
const userId = 123;
fetchUserData(userId)
.then((user) => {
console.log("User data:", user);
return fetchUserPosts(user.userId);
})
.then((posts) => {
console.log("User posts:", posts);
return processPosts(posts);
})
.then((processedPosts) => {
console.log("Processed posts:", processedPosts);
})
.catch((error) => {
console.error("Error:", error);
});
This code simulates fetching user data, then fetching posts for that user, and finally processing the posts. Each operation waits for the previous one to complete, ensuring the correct sequence. β¨
Tips and Best Practices
- Use
catch()
for Error Handling: Always include acatch()
block at the end of your Promise chains to handle any rejections that occur. - Avoid Nested
then()
: Nestedthen()
calls can make your code harder to read. Prefer chaining. - Return Values or Promises: Ensure that your
onFulfilled
callbacks return a value or a Promise to maintain the chain. - Keep Callbacks Concise: Keep your
onFulfilled
andonRejected
callbacks short and focused. For complex logic, move the code to separate functions.
Conclusion
The then()
method is a powerful tool for managing asynchronous operations in JavaScript. By understanding how to use then()
to handle promise resolutions, chain asynchronous operations, and manage errors, you can write cleaner, more maintainable code. Remember to always include error handling and follow best practices to ensure your asynchronous code is robust and reliable. π