Lesson 23 of 50 – Promises
46% Completed
46%

Node.js Promises

A Promise in JavaScript represents the eventual completion or failure of an asynchronous operation. Promises help us organize asynchronous code without deeply nesting callbacks.

In simple words: A Promise represents a result that may become available now, later, or after an operation fails.

1. What Is a Promise?

A Promise is an object used to handle the result of an asynchronous operation. It can be fulfilled with a value or rejected with a reason, such as an error.

The Three States of a Promise
State Meaning
Pending The operation has not settled yet.
Fulfilled The operation completed successfully.
Rejected The operation failed.
Once a Promise is fulfilled or rejected, it is settled and cannot change to another state.

2. Create Your First Promise

We create a Promise using the new Promise() constructor. Its executor function receives two functions: resolve() and reject().

Example: A Successful Promise
const myPromise = new Promise((resolve, reject) => {
    resolve('Operation successful!');
});

myPromise.then((result) => {
    console.log(result);
});
Output:
Operation successful!

The resolve() function fulfills the Promise. The .then() method handles its successful result.

3. Using resolve() and reject()

Use resolve() to fulfill a Promise and reject() to reject it.

Example: Resolve a Promise
const promise = new Promise((resolve, reject) => {
    const marks = 80;

    if (marks >= 40) {
        resolve('Student passed!');
    } else {
        reject(new Error('Student failed.'));
    }
});

promise
    .then((message) => {
        console.log(message);
    })
    .catch((error) => {
        console.log(error.message);
    });
Output:
Student passed!

Since the marks are 80, the Promise is fulfilled. If the marks were below 40, it would be rejected.

4. Using then()

The .then() method registers handlers for a fulfilled Promise. It can also accept a rejection handler as its second argument, although .catch() is often clearer for error handling.

Example: Handle a Successful Result
const promise = Promise.resolve(100);

promise.then((value) => {
    console.log('Value:', value);
});
Output:
Value: 100

Promise.resolve(100) creates a fulfilled Promise containing the value 100.

5. Using catch()

The .catch() method handles a rejected Promise. It is commonly used to handle errors from a Promise chain.

Example: Handle a Rejected Promise
const promise = new Promise((resolve, reject) => {
    reject(new Error('Something went wrong!'));
});

promise
    .then((result) => {
        console.log(result);
    })
    .catch((error) => {
        console.log('Error:', error.message);
    });
Output:
Error: Something went wrong!

Because the Promise is rejected, the .catch() handler processes the error.

6. Using finally()

The .finally() method runs when a Promise settles, whether it fulfills or rejects. It is useful for cleanup tasks.

Example: finally()
Promise.resolve('Data loaded')
    .then((result) => {
        console.log(result);
    })
    .catch((error) => {
        console.log(error.message);
    })
    .finally(() => {
        console.log('Operation finished.');
    });
Output:
Data loaded
Operation finished.

The finally() callback runs after the Promise settles, regardless of whether it succeeds or fails.

7. Promise Chaining

Promise chaining allows us to perform multiple operations in sequence. Each .then() can return a value or another Promise for the next step.

Example: Perform Calculations
Promise.resolve(10)
    .then((number) => {
        console.log('Original:', number);
        return number + 5;
    })
    .then((number) => {
        console.log('After addition:', number);
        return number * 2;
    })
    .then((number) => {
        console.log('Final result:', number);
    })
    .catch((error) => {
        console.log('Error:', error.message);
    });
Output:
Original: 10
After addition: 15
Final result: 30

Each handler returns a value that becomes the input for the next fulfilled handler.

8. Promise with setTimeout()

We can create a Promise that fulfills after a delay. This technique is useful for learning asynchronous execution.

Example: Delayed Promise
function getMessage() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve('Message received!');
        }, 2000);
    });
}

console.log('Start');

getMessage().then((message) => {
    console.log(message);
});

console.log('End');
Output:
Start
End
Message received!

The Promise fulfills after approximately two seconds. The synchronous console.log() statements execute first.

9. Promise.resolve() and Promise.reject()

These static methods create fulfilled or rejected Promises. They are useful when a Promise is needed without writing the constructor directly.

Example: resolve() and reject()
Promise.resolve('Success')
    .then((message) => {
        console.log(message);
    });

Promise.reject(new Error('Failure'))
    .catch((error) => {
        console.log(error.message);
    });
Output:
Success
Failure

Promise handlers run asynchronously as microtasks. The two independent examples above schedule their handlers in the order shown.

10. Promise.all()

Promise.all() accepts an iterable of Promises and fulfills when all of them fulfill. If any input Promise rejects, the returned Promise rejects with that reason.

Example: Run Multiple Promises
const p1 = Promise.resolve('Student data');
const p2 = Promise.resolve('Course data');
const p3 = Promise.resolve('Fee data');

Promise.all([p1, p2, p3])
    .then((results) => {
        console.log(results);
    })
    .catch((error) => {
        console.log('Error:', error.message);
    });
Output:
[
  'Student data',
  'Course data',
  'Fee data'
]

The results are returned in the same order as the input Promises, not necessarily in the order they finish.

11. Promise.allSettled()

Promise.allSettled() waits for every input Promise to settle. Its result describes whether each Promise fulfilled or rejected.

Example: Check Every Result
const p1 = Promise.resolve('Success');
const p2 = Promise.reject(new Error('Failed'));

Promise.allSettled([p1, p2]).then((results) => {
    results.forEach((result) => {
        console.log(result.status);
    });
});
Output:
fulfilled
rejected

Unlike Promise.all(), Promise.allSettled() reports the outcome of every input Promise.

12. Important Promise Methods

Method Purpose
.then() Handles fulfillment and returns a new Promise.
.catch() Handles rejection and returns a new Promise.
.finally() Runs cleanup logic after settlement.
Promise.resolve() Creates a fulfilled Promise or adopts a Promise-like result.
Promise.reject() Creates a rejected Promise.
Promise.all() Fulfills when all inputs fulfill; rejects if an input rejects.
Promise.allSettled() Waits for every input Promise to settle.
Promise.race() Settles with the first input Promise to settle.
Promise.any() Fulfills with the first fulfilled input, or rejects if all reject.

13. Practical Example: Student Result

This example checks a student's marks using a Promise and displays the result.

Complete Program
function checkResult(marks) {
    return new Promise((resolve, reject) => {
        if (marks >= 40) {
            resolve('Congratulations! You passed.');
        } else {
            reject(new Error('Sorry! You failed.'));
        }
    });
}

checkResult(75)
    .then((message) => {
        console.log(message);
    })
    .catch((error) => {
        console.log(error.message);
    })
    .finally(() => {
        console.log('Result checking completed.');
    });
Output:
Congratulations! You passed.
Result checking completed.

Try changing 75 to 25 and run the program again to see the rejected result.

📝 Practical Assignment

Practice Tasks
Write programs to complete these tasks:
  1. Create a Promise that displays a success message.
  2. Create a rejected Promise and handle it with .catch().
  3. Use .finally() to display a completion message.
  4. Create a Promise that checks whether a student has passed.
  5. Chain three calculations using .then().
  6. Use Promise.all() to collect three results.
  7. Use Promise.allSettled() to inspect successful and failed Promises.

Challenge: Create three Promise-based functions to get a student, course, and fee. Chain them together and handle errors in one place.


🧠 Quiz – Node.js Promises

Select the correct answer for each question.

1. How many main states does a Promise have?

2. Which method is commonly used to handle a rejected Promise?

3. Which method waits for every input Promise to settle?