Skip to main content

Command Palette

Search for a command to run...

JavaScript Promises Explained for Beginners

Updated
7 min read
JavaScript Promises Explained for Beginners

Introduction

JavaScript is single-threaded, meaning it executes one task at a time.

But modern applications often perform slow operations like:

  • API requests

  • Database queries

  • File reading

  • Timers

If JavaScript waited for every slow operation to finish before continuing, applications would become slow and unresponsive.

To solve this problem, JavaScript introduced:

Promises

Promises make asynchronous code:

  • Cleaner

  • Easier to read

  • Easier to manage

In this article, we will learn:

  • What problem promises solve

  • Promise states

  • Promise lifecycle

  • Handling success and failure

  • Promise chaining

  • Why promises improved JavaScript development


The Problem Before Promises

Before promises, JavaScript mainly used:

Callbacks

Callbacks worked, but large applications became difficult to manage.


Callback Example

setTimeout(() => {
  console.log("Task completed");
}, 2000);

This is a callback.


Callback Nesting Problem

Imagine multiple async operations.

Example:

getUser(function () {
  getPosts(function () {
    getComments(function () {
      console.log("Done");
    });
  });
});

This creates deeply nested code.


Why Callback Nesting Is Bad

Problems:

  • Hard to read

  • Hard to debug

  • Difficult to maintain

This problem is often called:

Callback Hell

Callback Hell Visualization

Task 1
  └── Task 2
        └── Task 3
              └── Task 4

Code becomes messy quickly.


What Is a Promise?

Simple definition:

A Promise is an object representing a future value.

A promise represents a task that:

  • May complete later

  • May succeed

  • May fail


Real-Life Analogy

Imagine ordering food online.

Order placed
      │
      ▼
Food preparing
      │
      ▼
Delivered OR Failed

That is similar to how promises work.


Promise Lifecycle

A promise goes through different states.


Promise States

A promise has 3 states:

  • Pending

  • Fulfilled

  • Rejected


1. Pending

Operation still running

Example:

Waiting for API response

2. Fulfilled

Operation completed successfully

3. Rejected

Operation failed

Example:

Network error

Promise Lifecycle Diagram

          Promise Created
                  │
                  ▼
              Pending
             /       \
            /         \
           ▼           ▼
     Fulfilled      Rejected

Creating a Promise

Promises are created using:

new Promise()

Basic Promise Syntax

const promise = new Promise((resolve, reject) => {

});

Understanding resolve and reject

Function Meaning
resolve() Promise succeeded
reject() Promise failed

Simple Promise Example

const promise = new Promise((resolve, reject) => {
  const success = true;

  if (success) {
    resolve("Task completed");
  } else {
    reject("Task failed");
  }
});

Handling Successful Promises

Use:

.then()

Example

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

Output:

Task completed

Handling Failed Promises

Use:

.catch()

Example

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

Output:

Task failed

Full Promise Example

const promise = new Promise((resolve, reject) => {
  const success = true;

  if (success) {
    resolve("Data loaded");
  } else {
    reject("Error loading data");
  }
});

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

Promise Flow Visualization

Promise Starts
      │
      ▼
   Pending
      │
 ┌────┴────┐
 ▼         ▼
Success   Failure
 │           │
 ▼           ▼
.then()   .catch()

Why Promises Improved JavaScript

Promises improved:

  • Readability

  • Error handling

  • Async flow management

Compared to callbacks, promises are much cleaner.


Callback vs Promise Comparison


Callback Style

getUser(function (user) {
  getPosts(user.id, function (posts) {
    getComments(posts[0], function (comments) {
      console.log(comments);
    });
  });
});

Promise Style

getUser()
  .then((user) => {
    return getPosts(user.id);
  })
  .then((posts) => {
    return getComments(posts[0]);
  })
  .then((comments) => {
    console.log(comments);
  });

Promises are easier to read.


What Is Promise Chaining?

Promise chaining means:

Connecting multiple .then() calls together.


Promise Chaining Example

const promise = Promise.resolve(5);

promise
  .then((num) => {
    return num * 2;
  })
  .then((result) => {
    console.log(result);
  });

Output:

10

How Chaining Works

Each .then() returns:

A new promise

which allows continuous chaining.


Promise Chaining Visualization

Promise
   │
   ▼
.then()
   │
   ▼
.then()
   │
   ▼
.then()

Error Handling in Promises

Promises make error handling cleaner.


Example

const promise = new Promise((resolve, reject) => {
  reject("Something went wrong");
});

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

Output:

Something went wrong

Why .catch() Is Powerful

Instead of handling errors everywhere:

One catch block can handle chain errors

Real-World Example: API Simulation

function fetchUser() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        name: "Ranjan",
      });
    }, 2000);
  });
}

fetchUser()
  .then((user) => {
    console.log(user);
  });

Output after 2 seconds:

{ name: 'Ranjan' }

Common Beginner Mistakes

1. Forgetting return in Chaining

Wrong:

.then(() => {

})

when next promise is needed.


2. Ignoring Errors

Always use:

.catch()

3. Confusing Promise with Result

Promise is:

Future value

not immediate data.


Difference Between Callback and Promise

Callback Promise
Nested structure Cleaner chaining
Harder error handling Centralized error handling
Callback hell possible Better readability

Best Practices

1. Always Handle Errors

Use:

.catch()

2. Keep Promise Chains Clean

Avoid unnecessary nesting.


3. Return Values Properly

Important for chaining.


Real-World Use Cases

Promises are heavily used in:

  • API requests

  • Database operations

  • File handling

  • Authentication

  • Async workflows


Mental Model

Think of a promise like an online order receipt.

Order placed now
Result arrives later

You do not get the product immediately, but you are promised a future result.


Full Working Example

function checkNumber(num) {
  return new Promise((resolve, reject) => {
    if (num > 10) {
      resolve("Number is greater than 10");
    } else {
      reject("Number is too small");
    }
  });
}

checkNumber(15)
  .then((message) => {
    console.log(message);
  })
  .catch((error) => {
    console.log(error);
  });

Output:

Number is greater than 10

Conclusion

Promises made asynchronous JavaScript much cleaner and easier to manage.

Key takeaways:

  • Promises represent future values

  • Promises solve callback nesting problems

  • Promise states are pending, fulfilled, and rejected

  • .then() handles success

  • .catch() handles errors

  • Promise chaining improves readability

Understanding promises is essential because modern JavaScript applications rely heavily on asynchronous programming.

2 views