Why Do We Even Need Promises?

🕰️ Problem: JavaScript is primarily synchronous, running one piece of code at a time.
Imagine JS as a one-man band — it can only do one thing at a time. But the world (like APIs, file reading, or user clicks) doesn't wait.

Let’s say:
You fetch data from a server.
It takes 2 seconds.
Meanwhile, your app shouldn’t freeze.
So we need a way to wait without blocking other work.

i think now we are clear about the problem right ? ok now lets understand about what exactly is promise.

🧃 The Juice Shop Analogy: Understanding Promises

Imagine you're at a juice shop:
You place an order for a mango juice.
The shopkeeper says, "It'll be ready in 5 minutes."
You receive a token and wait.

After 5 minutes:

If the juice is ready, you get it. ✅
If mangoes are out of stock, you're informed. ❌

In JavaScript, this scenario shows how Promises work.

🧠 So, What is a Promise in JavaScript?

A Promise is like a "contract" that says:

“I promise to give you something in the future — either a success or a failure.”

🔄 The 3 States of a Promise:

JavaScript Promise States

State Meaning
🕒 Pending Still waiting. Not ready yet.
✅ Fulfilled Promise kept. Success! Got the result.
❌ Rejected Something went wrong. It failed.

🧪 Let’s Try a Simple Example (No need to panic)

const juicePromise = new Promise((resolve, reject) => {
  let mangoes = true;

  if (mangoes) {
    resolve("Here is your mango juice!");
  } else {
    reject("Sorry, no mangoes today.");
  }
});

juicePromise
  .then(result => console.log(result))  // when successful
  .catch(error => console.log(error)); // when failed

⏱️ Why Use Promises?

Because JavaScript is single-threaded. That means it can only do one thing at a time. So if you wait 5 seconds to get data from a server, JavaScript would freeze your whole website.

Promises let JS do something else while waiting.

😵‍💫 Old Way: Callback Hell (Before Promises)

getData(function(result) {
  processData(result, function(final) {
    displayData(final, function() {
      // more and more nesting 😭
    });
  });
});

Too many () inside () inside () = messy and hard to read.

🦸‍♂️ Superhero: Promises to the Rescue

getData()
  .then(processData)
  .then(displayData)
  .catch(error => console.log(error));

Cleaner, right? 😊

🧱 Let's Understand Promise Chaining

Every .then() returns a new promise. You can chain .then() to run things in order.

function first() {
  return new Promise(resolve => setTimeout(() => resolve("Step 1 done"), 1000));
}

function second(data) {
  return new Promise(resolve => setTimeout(() => resolve(data + " → Step 2 done"), 1000));
}

first()
  .then(result => second(result))
  .then(final => console.log(final));

Output: Step 1 done → Step 2 done (after 2 seconds)

🔃 What is async/await and Why is it Cool?

Problem: .then() is better than callbacks, but still not very “human-friendly”.

Let’s rewrite using async/await (which works on top of promises):

function getJuice() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("Here's your juice!");
    }, 2000);
  });
}

async function serveJuice() {
  console.log("Ordering juice...");
  const result = await getJuice();  // wait until juice is ready
  console.log(result);
}

serveJuice();

output:

Ordering juice...
(wait 2 sec)
Here's your juice!

Why it’s easier?

  • No .then()
  • Looks like normal code, but still async!
  • Easier to debug and read

⚡ Parallel vs Sequential

const user = await getUser();   // wait 1 sec
const posts = await getPosts(); // wait 1 sec

Takes 2 seconds total right ? yes it will took 2 sec but what if we can do this same thing in 1 sec ? yes you heard it right . we can do same thing in 1 sec and that's parallel way.

✅ Parallel: Run together

const [user, posts] = await Promise.all([getUser(), getPosts()]);

Takes 1 second only!

❌ Mixing await with normal functions

await getSomething(); // ❌ ERROR if not inside async
async function doIt() {
  await getSomething(); // ✅
}

lets try to recall all of the above things and know the things to handle the asynchronous events in JS.

🕰️ Evolution of Asynchronous Handling in JavaScript

1)📞 Callbacks (The Beginning)

What is it?

  • A function passed as an argument to be called after another function finishes.
  • The earliest way to handle async behavior in JavaScript.

Problem:

  • Callback Hell (nested pyramid of doom).
  • Hard to read, debug, and maintain.

example:

function getData(callback) {
  setTimeout(() => {
    callback("📦 Data received");
  }, 1000);
}

getData(function(result) {
  console.log(result);
});

2)🔮 Promises (Introduced in ES6 - 2015)

What is it?
An object that represents a value that may not be available yet, but will be resolved in the future.

Uses .then() for success and .catch() for errors.

Improvement:

  • Avoids nesting by using chaining.
  • Easier error handling

example:

function getData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("📦 Data from promise");
    }, 1000);
  });
}

getData()
  .then(result => console.log(result))
  .catch(error => console.error(error));

3)🧙 Async/Await (Introduced in ES8 - 2017)

What is it?

  • Syntactic sugar over promises.
  • Makes async code look synchronous.
  • Works only inside async functions.

Improvement:

  • Cleaner, more readable.
  • Try/catch block makes error handling familiar.

example:

async function fetchData() {
  try {
    const result = await getData();
    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

fetchData();

4)🧩 Top-level Await (Introduced in ES2022)

What is it?

Allows you to use await outside of an async function.
Mostly used in modules or top-level script files.

Improvement:
Useful for initialization scripts, loading configs, or data before app starts.

example:

const result = await fetch("https://api.example.com/data");
const data = await result.json();
console.log(data);

Must be in a module or a supported runtime like Deno or modern Node.js (with "type": "module").

5)🛠️ Newer Promise Features

not new paradigms, but powerful tools

5.1. Promise.all()
Run multiple promises in parallel and wait for all.

Promise.all([getUser(), getPosts(), getComments()])
  .then(([user, posts, comments]) => console.log(user, posts, comments));

5.2. Promise.race()
Resolves/rejects as soon as any one of the promises does.

5.3. Promise.allSettled()
Waits for all promises to finish (regardless of success or failure).

📕 Summary

JavaScript Promise Concept Cheat Sheet

Concept Meaning
Promise "I’ll give it to you later"
resolve "Here you go!"
reject "Sorry, can't do it."
.then() "What to do after it’s done"
.catch() "What to do if it failed"
async Tells JS this function uses await inside
await "Wait here until I get the result"

📊 Summary Table: Async Handling in JavaScript

Approach Introduced In Syntax Style Pros Cons Example Keywords
Callbacks Before ES6 Function-based Simple, works everywhere Callback Hell, hard to manage function(cb) {}
Promises ES6 (2015) Chain-based Cleaner than callbacks, chaining Can still get nested .then(), .catch()
Async/Await ES8 (2017) Synchronous-like Easy to read, debug, write Only usable inside async funcs async, await
Top-level Await ES2022 Global await usage Useful in modules Not supported everywhere await (no func wrapper)
Promise utilities ES6+ Combined use Advanced control flow Must understand promises well Promise.all(), race()

Want to Try It Yourself?

Here’s a simple test you can run in your browser console or in JSFiddle:

function makeTea() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("☕ Tea is ready!");
    }, 1500);
  });
}

async function startDay() {
  console.log("Starting the day...");
  const tea = await makeTea();
  console.log(tea);
}

startDay();

💡 Pro Tip: Always choose the approach that keeps your code clean and readable. async/await is your best friend in modern JavaScript!

i will post all promises methods in an interesting way in next blog soon . the above content is just to make you familiar about promises and async and await .

stay tuned !!
Happy Learning !!