devnotes.

Promises Fundamentals

A promise represents a value that may not be available yet. It's always in one of three states: pending, fulfilled, or rejected — and once settled, its state never changes again.

function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) resolve({ id, name: "Rahim" });
      else reject(new Error("Invalid id"));
    }, 500);
  });
}

fetchUser(1)
  .then(user => console.log(user))
  .catch(err => console.error(err))
  .finally(() => console.log("Done"));

.then() registers a callback for when the promise fulfills, .catch() for when it rejects, and .finally() runs regardless of the outcome — useful for cleanup like hiding a loading spinner. Each of these methods returns a new promise, which is why they can be chained in sequence, with each .then() receiving the value returned by the one before it.

Promise.all([...]) waits for every promise in an array to fulfill (or rejects immediately if any one does), while Promise.race([...]) settles as soon as the first one does — both useful for coordinating multiple concurrent operations.