Skip to content
5 min read

JavaScript Promises Explained Before You Learn async/await

Understand JavaScript Promises from scratch before diving into async/await. Learn what a Promise is, how .then() and .catch() work, and how to chain multiple async operations.

#javascript #async #frontend #beginner

Before async/await existed, JavaScript Promises were the solution to callback hell. Even though async/await is now preferred, understanding Promises is essential — because async/await is built on top of them, and you’ll encounter them in documentation and older codebases constantly.

What Is a Promise?

A Promise represents a value that isn’t available yet but will be in the future. Think of it like ordering food at a restaurant — you get a ticket (the Promise) and eventually your food arrives (the value) or the kitchen runs out of ingredients (an error).

A Promise is always in one of three states:

  • Pending — the operation is still running
  • Fulfilled — it completed successfully
  • Rejected — it failed

Creating a Promise

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

  if (success) {
    resolve("Data loaded!");   // Fulfilled
  } else {
    reject("Something failed"); // Rejected
  }
});

In practice, you rarely create Promises manually — fetch(), database drivers, and many APIs return them automatically.

Consuming Promises with .then() and .catch()

fetch("https://api.github.com/users/kaikobud")
  .then(response => response.json())   // runs on success
  .then(data => {
    console.log(data.name);
    return data.public_repos;          // pass value to next .then()
  })
  .then(repoCount => console.log(`Repos: ${repoCount}`))
  .catch(error => console.error(error)) // runs on any failure
  .finally(() => console.log("Done")); // always runs

Each .then() returns a new Promise, enabling chaining.

Promise.all — Run Multiple Promises in Parallel

const p1 = fetch("/api/users").then(r => r.json());
const p2 = fetch("/api/posts").then(r => r.json());
const p3 = fetch("/api/tags").then(r => r.json());

Promise.all([p1, p2, p3]).then(([users, posts, tags]) => {
  console.log(users, posts, tags);
});

Promise.all waits for all promises to resolve. If any one rejects, the entire thing rejects.

Conclusion

JavaScript Promises are the foundation of all async JavaScript. Even if you prefer async/await (which you should), understanding how .then(), .catch(), and Promise.all() work makes you a much more effective developer. Every time you use await, there’s a Promise underneath.

Read next: async/await in JavaScript

External resource: MDN — Using Promises

Kaikobud Sarkar

Kaikobud Sarkar

Software engineer passionate about backend technologies and continuous learning. I write about Python frameworks, cloud architecture, engineering growth, and staying current in tech.

Related Articles

How to Write Clean Functions in JavaScript

Learn how to write clean JavaScript functions that are easy to read, test, and maintain. This guide covers naming, single responsibility, pure functions, and avoiding common pitfalls.

#javascript #bestpractices

CSS Flexbox in Plain English: A Beginner's Guide

Learn CSS Flexbox with simple, visual explanations. This guide covers display flex, justify-content, align-items, flex-wrap, and practical layouts every developer needs to know.

#css #flexbox