Skip to main content

Command Palette

Search for a command to run...

JavaScript Promises Explained for Beginners

Before and After the Promise function of JavaScript

Updated
•4 min read•View as Markdown
JavaScript Promises Explained for Beginners

In traditional way JavaScript was handled asynchronous operations by using very messy code. Promises were introduced to solve that problem and make async code cleaner and more readable.

Let’s break it down step by step.

What is a Promise?

In JavaScript Promise acts like a placeholder of value that not available yet, allowing us to handle asynchronous code in a cleaner, more manageable way.

It's like ordering something

  • we ordered -> pending

  • order delivered -> fulfilled (resolve)

  • order cancel -> rejected

What problem promises solve

Before Promise, JavaScript was heavily depend on callback functions.

But the problem of callback is callback hell (nested callback)

Example

function loginUser(username, password, callback) {
    setTimeout(() => {
        console.log(`User Logged in`);
        callback({ userId: 1 });
    }, 1000)
}

function getUserData(userId, callback) { 
    setTimeout(() => { 
        console.log(Fetch user data); 
        callback({ name: "Janardan" }); 
    }, 1000) 
}

function getOders(username, callback) {
    setTimeout(() => {
        console.log(`Fetch Oders`);
        callback(["Order1", "Order2"]);
    }, 1000)
}

function processPayment(orders, callback) {
     setTimeout(() => { 
         console.log(Payment processed);
         callback(Success); 
     }, 1000) 
}

//callback hell (How was call before Promise)
loginUser("Janardan", '1234', (user) => {
    getUserData(user.userId, (userData) => {
        getOders(userData.name, (orders) => {
            processPayment(orders, (status) => {
                console.log(`Final Status ${status}`);
            })
        })
    })
})

output ->

User Logged in 
Fetch user data 
Fetch Oders 
Payment processed 
Final Status Success

Here, we can confuse which callback need to call in which function ??

Now with the Promise

function loginUser() {
    return new Promise((resolve)=>{
        setTimeout(() => {
            console.log(`User Logged in`);
            resolve({ userId: 1 });
        }, 1000);
    });
}

function getUserData(userId) {
    return new Promise((resolve)=>{
        setTimeout(() => {
            console.log(Fetch user data); 
            resolve({ name: "Janardan" });
        }, 1000);
    });
}

function getOrders(userName) {
    return new Promise((resolve)=>{
        setTimeout(() => {
        console.log(`Fetch Oders`);
        resolve(["Order1", "Order2"]);
    }, 1000)
    });
}

function processPayment(orders) {
    return new Promise((resolve)=>{
        setTimeout(() => {
        console.log("Payment processed");
         resolve("Success");
    }, 1000)
    });
}

//Clean flow with Promise
loginUser().then(user => getUserData(user.userId))
    .then(userData => getOrders(userData.name))
    .then(orders => processPayment(orders))
    .then(status => console.log(`Final Status ${status}`))
    .catch(err => console.log(err))

very easy to handle.

Promise States

Pending

  • Initial state

  • Work is still in progress

Fulfilled (Resolved)

  • Operation completed successfully

  • You get the result

Rejected

  • Something went wrong

  • You get an error

Basic Promise Lifecycle

Step 1: Create a Promise

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

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

Step 2: Consume the Promise

myPromise
  .then(result => {
    console.log(result); // success
  })
  .catch(error => {
    console.error(error); // failure
  })
  .finally(() => {
    console.log("Always runs");
  });

Handling Success and Failure

.then() -> for Sucess

.catch() -> for Errors

.finally() -> Always run

const data_API = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({
            name: "Janardan Mondal",
            age: 27,
            city: "Kolkata",
        });
    }, 2000);
});

data_API.then((data) => {
    console.log(`The name of the person is ${data.name}`);
}).catch((err) => {
    console.log(`The Errors: ${err}`);
}).finally(() => {
    console.log("Data fetching process is completed.");
})

Promise Chaining

Promise chaining lets you run async steps in sequence.

//from the first example 
//Clean flow with Promise
loginUser()
    .then(user => getUserData(user.userId))
    .then(userData => getOrders(userData.name))
    .then(orders => processPayment(orders))
    .then(status => console.log(`Final Status ${status}`))
    .catch(err => console.log(err))

Always return a value or promise inside .then()

.then(data => { 
    return processData(data); // important! 
})

//or

.then(data => processData(data)) // important! 

Promises vs Callbacks

Feature Callbacks Promises
Readability ❌ Poor (nested) ✅ Clean (chained)
Error Handling ❌ Scattered ✅ Centralized
Flow Control ❌ Hard ✅ Easy
Debugging ❌ Difficult ✅ Easier

Visual Flow Promise Lifecycle

   Promise Created
          |
       Pending
      /       \
Fulfilled  Rejected 
    |          |  
 then()      catch() 
   | 
finally()

Why promise is so important

  • Prevent callback hell

  • Improve code readability

  • Make async flow predictable

  • Provide better error handling

So, without blocking the main thread it's help to run async code and also they provide a structured and more clean to read.