# Promise Chaining

JavaScript Promises are a powerful tool for handling asynchronous operations. They help in avoiding callback hell and making the code more readable. Promise chaining is a pattern where multiple asynchronous operations are chained together using the `.then()` method, where each operation starts after the previous one finishes.

**What is a Promise?**

A Promise in JavaScript is an object representing the eventual completion or failure of an asynchronous operation. It has three states:

1. **Pending**: Initial state, neither fulfilled nor rejected.
2. **Fulfilled**: Operation completed successfully.
3. **Rejected**: Operation failed.

**Creating a Promise**

Here's a simple example of creating a Promise:

```javascript
let promise = new Promise((resolve, reject) => {
    let success = true; // Change this to false to see the reject case
    if (success) {
        resolve("Operation succeeded");
    } else {
        reject("Operation failed");
    }
});

promise.then(result => {
    console.log(result);
}).catch(error => {
    console.error(error);
});
```

**Promise Chaining**

Promise chaining allows us to perform a sequence of asynchronous operations, where each operation starts after the previous one completes. This is done by returning a new promise from the `.then()` method.

**Example Scenario: Fetching Data from APIs**

Consider a scenario where we need to:

1. Fetch user data from an API.
2. Fetch the user's posts based on the user data.
3. Fetch comments on each post.

Here’s how you can achieve this using promise chaining:

```javascript
// Simulate an API call to fetch user data
function fetchUser() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ userId: 1, username: "john_doe" });
        }, 1000);
    });
}

// Simulate an API call to fetch posts for a user
function fetchPosts(userId) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve([
                { postId: 1, title: "Post 1" },
                { postId: 2, title: "Post 2" }
            ]);
        }, 1000);
    });
}

// Simulate an API call to fetch comments for a post
function fetchComments(postId) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve([
                { commentId: 1, content: "Great post!" },
                { commentId: 2, content: "Thanks for sharing." }
            ]);
        }, 1000);
    });
}

// Using promise chaining to perform the operations sequentially
fetchUser()
    .then(user => {
        console.log("User Data:", user);
        return fetchPosts(user.userId);
    })
    .then(posts => {
        console.log("User Posts:", posts);
        // Fetch comments for the first post
        return fetchComments(posts[0].postId);
    })
    .then(comments => {
        console.log("Post Comments:", comments);
    })
    .catch(error => {
        console.error("Error:", error);
    });
```

#### Explanation

1. **fetchUser()**: Returns a promise that resolves with user data after 1 second.
2. **fetchPosts(userId)**: Takes a userId and returns a promise that resolves with an array of posts after 1 second.
3. **fetchComments(postId)**: Takes a postId and returns a promise that resolves with an array of comments after 1 second.

The chaining is done using `.then()`:

* The first `.then()` takes the resolved user data and calls `fetchPosts(user.userId)`.
* The second `.then()` takes the resolved posts and calls `fetchComments(posts[0].postId)` for the first post.
* The final `.then()` logs the comments of the first post.

If any promise in the chain is rejected, the `.catch()` method will handle the error.

#### Advantages of Promise Chaining

* **Readability**: Makes asynchronous code easier to read and maintain.
* **Error Handling**: Centralized error handling using `.catch()`.
* **Sequential Execution**: Ensures that asynchronous operations are performed in a specific order.

#### Conclusion

Promise chaining is a powerful technique to handle sequences of asynchronous operations in a clean and readable manner. By returning promises from the `.then()` method, you can create complex workflows that are easy to understand and maintain. Use it to improve the structure of your asynchronous JavaScript code and avoid callback hell.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://guvi.gitbook.io/fsd/docs/module-4-advance-js/promise/promise-chaining.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
