Skip to the content.

In JavaScript, Promises are used to handle asynchronous operations, allowing you to work with values that might not yet be available, but will be resolved in the future. A promise can be in one of three states:

A promise is created using the new Promise() constructor, where you provide an executor function that takes two arguments: resolve and reject.

Example of a Promise:

const myPromise = new Promise((resolve, reject) => {
    let success = true;  // Simulating a success or failure condition

    if (success) {
        resolve("Operation successful!");  // Resolve the promise with a value
    } else {
        reject("Something went wrong!");  // Reject the promise with an error message
    }
});

Key Methods for Handling Promises

  1. then(): The then() method is used to define what should happen when the promise is resolved (success). It accepts two callbacks:
    • The first callback is called when the promise is resolved (success case).
    • The second callback (optional) is called when the promise is rejected (error case).
myPromise
    .then(result => {
        console.log(result);  // Handles the resolved value
    })
    .catch(error => {
        console.log(error);  // Handles any errors from rejection
    });
  1. catch(): The catch() method is used to handle errors. It acts like the second argument in the then() method, but is a cleaner and more explicit way to handle promise rejections.
myPromise
    .catch(error => {
        console.log(error);  // Handle promise rejection
    });
  1. finally(): The finally() method is used to specify code that should run after the promise is settled (whether it is resolved or rejected). It doesn’t receive any arguments, and it’s often used for clean-up actions.
myPromise
    .finally(() => {
        console.log("Promise settled (either resolved or rejected).");
    });

Full Example:

const myPromise = new Promise((resolve, reject) => {
    let success = false;  // Simulating failure

    if (success) {
        resolve("Success!");
    } else {
        reject("Error occurred.");
    }
});

myPromise
    .then(result => {
        console.log(result);  // This will not be executed since the promise is rejected
    })
    .catch(error => {
        console.error(error);  // This will handle the rejection
    })
    .finally(() => {
        console.log("Promise is settled (done).");
    });

Summary:

Promises allow you to write asynchronous code in a more readable and manageable way, chaining operations and handling errors more easily.

Question on Promise from IITM BS Degree

Now, code Breakdown for the question:

new Promise((error, pass) => {
    if (5 === "5") {
        error(5); // This is used to resolve the promise with value 5.
    } else {
        pass(8); // This should reject the promise with value 8.
    }
})

Flow of the Promise Chain:

1. The Promise Constructor:

2. First .then():

.then(d => {
    console.log("Checkpoint 4", d); // This won't be called because the promise was rejected.
    throw new Error(20); // This won't be executed.
    return d * 5; // This won't be executed either.
})

3. Second .then() (Rejection Handler):

.then(
    d => { 
        console.log("Checkpoint 2", d); // This doesn't run, as the promise was rejected
        return d;
    },
    d => { 
        console.log("Checkpoint 5", d.message); // Logs "Checkpoint 5 undefined", since `d` is the rejection value (a number, not an error object)
        return d.message * 2; // This will be NaN because d.message is undefined.
    }
)

4. .catch():

.catch(e => {
    console.log("Checkpoint 3", e.message); // This won't run because the error is handled by the second `then()`.
    return e.message * 2;
})

5. .finally():

.finally(d => {
    console.log("Checkpoint 1", d); // Logs "Checkpoint 1 undefined" because `d` is `undefined` here.
    return d * 5; // Returns NaN because `undefined * 5` is NaN.
})

6. Final .then():

.then(d => {
    console.log("Checkpoint 6", d); // Logs "Checkpoint 6 NaN".
    return d * 5; // Returns NaN.
})

Final Output:

Conclusion: