Skip to main content

Command Palette

Search for a command to run...

JavaScript Promises Explained for Beginners

Updated
JavaScript Promises Explained for Beginners
A
I’m a Backend Developer currently learning and growing into Full-Stack Web Development. My main focus is building clean, reliable backend APIs using Node.js, Express, MongoDB, and Redis, while gradually improving my frontend and full-stack skills. On this blog, I share simple, practical explanations of what I’m learning in backend concepts, real development problems, and full-stack topics written in a way that’s easy to understand for other learners. 🎯 Open to Backend Developer / Software Engineer roles 📩 Contact: ashishjha1304@gmail.com

You write async code like this…

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

Looks confusing right? This is called callback hell

Now look at this:

getUser()
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))
  .then(comments => console.log(comments))
  .catch(err => console.log(err));

Clean, Readable, Easy to debug

That’s why Promises exist


This is the Problem Promises Solve

Before Promises:

  • Deep nested code (callback hell)

  • Hard to read and maintain

  • Error handling is messy

  • Debugging is painful


Example Problem

Imagine:

  1. Get user

  2. Then get posts

  3. Then get comments

With callbacks → nested pyramid
With promises → straight flow


What is a Promise?

A Promise is:

A value that will be available in the future


Imagine:

Ordering food online:

Order placed → Pending, Delivered → Fulfilled, Cancelled → Rejected
That’s exactly how Promises behave


Important

Promise is: Not immediate, Asynchronous, Future-based value


Promise States - IMP


1. Pending

Initial state, Work is still happening

Example: API request is in progress


2. Fulfilled

Operation successful, Result is returned

Example: Data received from server


3. Rejected

Operation failed
Error is returned

Example: Network error


Visual Flow

Pending → Fulfilled
        → Rejected

Creating a Promise:


Basic Syntax

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

  if (success) {
    resolve("Data received");
  } else {
    reject("Error occurred");
  }
});

Explanation:

  • new Promise() → create promise

  • resolve() → success

  • reject() → failure


Think Like This

  • resolve → success path

  • reject → error path


Handling Success and Failure


Using .then() and .catch()

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

Explanation

  • .then() → runs when success happens

  • .catch() → runs when error happens


Mental Model

Promise = “If this works → do this, else → do that”


Promise Lifecycle (Full Flow)

Create → Pending → (resolve/reject) → then/catch

Flow Example

fetchData()
  .then(data => processData(data))
  .then(result => console.log(result))
  .catch(err => console.log(err));

What happens here?

  1. First async task runs

  2. When done → .then() runs

  3. Next step runs

  4. If error → .catch() handles


Promise Chaining (VERY IMPORTANT)


Without chaining (bad)

Nested again:

getUser(function(user) {
  getPosts(user.id, function(posts) {
    console.log(posts);
  });
});

With chaining (good)

getUser()
  .then(user => getPosts(user.id))
  .then(posts => console.log(posts))
  .catch(err => console.log(err));

Why chaining is powerful?

  • No nesting

  • Easy to read

  • Step-by-step logic

  • Better error handling


Rule

Always return inside .then()

.then(user => {
  return getPosts(user.id);
})

Callback vs Promise


Callback Style

login(user, function(data) {
  getProfile(data, function(profile) {
    console.log(profile);
  });
});

Promise Style

login(user)
  .then(data => getProfile(data))
  .then(profile => console.log(profile))
  .catch(err => console.log(err));

Difference

Callback Promise
Nested Flat
Hard to read Easy
Multiple error handling Single catch

Mental Model (Best Way to Remember)


Promise = Pipeline

Step 1 → Step 2 → Step 3 → Result

Each .then() = next step


Final Thought

Promises don’t make async code faster.

They make it understandable

More from this blog

A

Ashish Jha · Dev

34 posts

A personal blog where I write simple and practical explanations about backend development, Git, JavaScript, and full-stack web development as I learn and build.