JavaScript Promises Explained (and How Async/Await Makes Them Sweeter)

JavaScript Promises Explained (and How Async/Await Makes Them Sweeter)

What do pizza orders, package tracking, and JavaScript have in common? More than you think..

Imagine you go to your favorite pizza place to order a large pizza. The moment you place the order, they don’t give you the pizza immediately — instead, they hand you a receipt with an order number.

  • When your pizza is ready → they call your number, and you pick it up hot and fresh.
  • If something goes wrong (say, the oven breaks) → they still let you know your order won’t be coming.

Everyone’s happy:

  • You → can chill at your table instead of staring at the oven.
  • The restaurant → can focus on making pizzas without you hovering.

It’s a win-win. And in programming, Promises do the same — they let you order up some data or a task, and get notified when it’s ready without blocking everything else.


The Programming Analogy

In JavaScript, this maps to:

  • Producer (the pizza chef) → code that takes time (e.g., network requests).
  • Consumers (the hungry customers) → functions that need the result when ready.
  • Promise (the order receipt) → connects the producing and consuming code.

A Promise ensures that once the result is ready (or an error occurs), all “subscribed” consumers get notified.

Think of it like package tracking:

  • You place the order (create the Promise).
  • You get a tracking number (the Promise object).
  • The package is either delivered (resolved) or returned to sender (rejected).


The Executor: Where the Work Happens

When you write:


Article content

  • The function you pass is called the executor — it’s your pizza chef in code form.
  • It’s automatically run when the Promise is created.
  • It gets two callbacks from JavaScript itself:

You can also think of this like booking concert tickets online:

  • The site confirms your booking (Promise creation).
  • If everything works → you get your tickets (resolve).
  • If the payment fails → you get a refund (reject).


Promise Internals

A Promise internally tracks two hidden properties:

  1. state — starts as "pending", then becomes "fulfilled" (resolved) or "rejected".
  2. result — starts as undefined, then becomes the value (if resolved) or the error (if rejected).

You can’t directly access these, but you can work with them using .then(), .catch(), and .finally().

It’s like checking your package’s tracking page: you can see the status (“out for delivery”) but you don’t have the driver’s steering wheel in your hands.


Consuming Promises

For success only:


Article content

For errors only:


Article content

.catch(f) is just a cleaner version of .then(null, f).


How async/await Fits In

async/await doesn’t replace Promises — it’s built on top of them. You can think of it as syntactic sugar for writing asynchronous code in a synchronous-looking style.

Here’s what that means:

  1. An async function always returns a Promise. Even if you return a normal value, JavaScript wraps it with Promise.resolve()
  2. await pauses execution inside an async function until the Promise resolves (or rejects).
  3. Why it’s called syntactic sugar Behind the scenes, the async/await version is transformed into Promise-based .then() code.

The difference is readability:

  • Sequential async steps look like normal top-to-bottom code.
  • Errors are handled with try...catch, which feels more natural than multiple .catch() calls.
  • Debugging is easier thanks to cleaner stack traces.


Final Thoughts

  • Promises are the backbone of modern async JavaScript — they connect producing and consuming code.
  • .then() and .catch() give you precise control, but can become verbose for multiple sequential tasks.
  • async/await makes your async code read like synchronous code while still being Promise-based.
  • Both are tools in your belt — use them where they shine.

Think of .then() as carefully tracking your pizza order number and waiting for the call, and async/await as having the chef personally bring the pizza to your table exactly when it’s ready.

The pizza is the same — but the experience feels different. And whether you’re ordering pizza, waiting for a package, or showing up for a movie you pre-booked, the underlying pattern is the same: request → wait → receive → enjoy.


I really enjoyed reading this article. This type of initiative really helps to understand the things more precisely and effectively. It would be immensely valuable if you continue writing in this manner. Truly appreciable!

Love this, Manish.. very insightful do continue writing these articles.

Manish, thank you very much. This has truly strengthened my foundational knowledge. I had been using async and await without fully understanding how they work, so this explanation has been extremely valuable.

That sounds like such a fun way to explain Promises! 🍕 Can’t wait to read your article.

To view or add a comment, sign in

Others also viewed

Explore content categories