Skip to main content

Command Palette

Search for a command to run...

JavaScript Promises Explained for Beginners

Updated
β€’3 min read

As JavaScript applications became more complex, handling asynchronous operations using callbacks started creating messy, hard-to-maintain code.

This is where Promises come in.

They provide a cleaner and more structured way to handle asynchronous operations.


πŸ”Ή What Problem Do Promises Solve?

🚨 Callback Hell

getUser(function(user) {
  getOrders(user.id, function(orders) {
    getOrderDetails(orders[0], function(details) {
      console.log(details);
    });
  });
});

❌ Deep nesting ❌ Hard to read ❌ Difficult to debug


βœ… With Promises

getUser()
  .then(user => getOrders(user.id))
  .then(orders => getOrderDetails(orders[0]))
  .then(details => console.log(details))
  .catch(err => console.error(err));

βœ” Flat structure βœ” Better readability βœ” Easier error handling


πŸ”Ή What is a Promise?

πŸ‘‰ A Promise is a placeholder for a value that will be available in the future.

Think of it like:

"I don’t have the data right now, but I promise I’ll give it to you later."


πŸ”Ή Promise States

A promise has 3 states:

  1. Pending

    • Initial state

    • Operation not completed yet

  2. Fulfilled

    • Operation successful

    • Value is available

  3. Rejected

    • Operation failed

    • Error is returned


πŸ“Œ Example

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

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

πŸ”Ή Basic Promise Lifecycle

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Done!");
  }, 2000);
});

promise
  .then(result => console.log(result))  // success
  .catch(error => console.error(error)) // failure
  .finally(() => console.log("Finished"));

πŸ” Flow

  1. Promise starts β†’ Pending

  2. After 2 sec β†’ Fulfilled

  3. .then() runs

  4. .finally() always runs


πŸ”Ή Handling Success and Failure

fetchData()
  .then(data => {
    console.log("Success:", data);
  })
  .catch(error => {
    console.log("Error:", error);
  });

βœ” .then() β†’ handles success βœ” .catch() β†’ handles errors


πŸ”Ή Promise Chaining

Promises allow sequential execution without nesting.

getUser()
  .then(user => getOrders(user.id))
  .then(orders => getOrdersDetails(orders))
  .then(details => console.log(details))
  .catch(err => console.error(err));

πŸ‘‰ Each .then() returns a new promise


πŸ”₯ Why Chaining Works

  • Each step waits for the previous one

  • No pyramid structure

  • Cleaner and more readable


πŸ”Ή Real-World Example

fetch("https://jsonplaceholder.typicode.com/posts/1")
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

πŸ”Ή Promises vs Callbacks

Feature Callbacks Promises
Structure Nested Flat (chained)
Readability Poor Good
Error Handling Manual Centralized (catch)
Maintainability Difficult Easier

πŸ”Ή Mental Model

  • Promise = future value

  • .then() = "When it's ready, do this"

  • .catch() = "If it fails, handle it"


πŸ”Ή Common Mistakes

❌ Not Returning Promise in Chain

getUser()
  .then(user => {
    getOrders(user.id); // ❌ missing return
  })
  .then(orders => console.log(orders)); // undefined

βœ” Always return the promise


❌ Multiple .then without Chain

promise.then(a => console.log(a));
promise.then(b => console.log(b));

πŸ‘‰ Runs independently (not sequential)


πŸš€ Why Promises Matter

  • Foundation of modern async JavaScript

  • Used in:

    • APIs (fetch)

    • Databases

    • File systems

  • Base for async/await

More from this blog

JavaScript Promises Explained for Beginners