Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

JavaScript Promises

What is a Promise?

A Promise is a JavaScript object that represents the eventual result of an asynchronous operation. Instead of passing callbacks into a function, a promise lets you attach handlers to the future success or failure of that operation. This makes async code much easier to read and reason about.

A Promise is always in one of three states:

  • Pending — the initial state; the operation has not completed yet.
  • Fulfilled — the operation completed successfully and the promise has a resolved value.
  • Rejected — the operation failed and the promise has a reason (error).

Once a promise is fulfilled or rejected it is settled and its state never changes again.

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

  if (success) {
    resolve('Operation succeeded!');
  } else {
    reject(new Error('Operation failed!'));
  }
});

promise
  .then(result => console.log(result))   // Operation succeeded!
  .catch(error => console.error(error));  // only runs on rejection

Chaining Promises

Each .then() returns a new promise, which allows you to chain multiple async steps in a readable sequence. The value returned from one .then() is passed as the argument to the next.

Promise Chaining
fetch('https://api.example.com/user/1')
  .then(response => response.json())       // parse JSON
  .then(user => {
    console.log(user.name);
    return fetch(`/api/posts?userId=${user.id}`);
  })
  .then(response => response.json())
  .then(posts => console.log(posts))
  .catch(error => console.error('Error:', error))
  .finally(() => console.log('Done'));     // always runs

Promise.all() — Run in Parallel

Promise.all() takes an array of promises and returns a single promise that resolves when all of them resolve, or rejects as soon as any one of them rejects. Use it when tasks are independent and can run simultaneously.

Promise.all()
const p1 = fetch('/api/users').then(r => r.json());
const p2 = fetch('/api/posts').then(r => r.json());
const p3 = fetch('/api/comments').then(r => r.json());

Promise.all([p1, p2, p3])
  .then(([users, posts, comments]) => {
    console.log(users, posts, comments);
  })
  .catch(err => console.error('One failed:', err));

Promise.allSettled(), race(), any()

JavaScript provides several other static methods for handling multiple promises:

  • Promise.allSettled() — waits for all promises to settle (fulfilled or rejected); never rejects. Returns an array of result objects.
  • Promise.race() — resolves or rejects as soon as the first promise settles.
  • Promise.any() — resolves as soon as the first promise fulfills; rejects only if all reject.
allSettled / race / any
const slow = new Promise(res => setTimeout(() => res('slow'), 2000));
const fast = new Promise(res => setTimeout(() => res('fast'), 500));
const fail = Promise.reject(new Error('failed'));

// allSettled — never rejects
Promise.allSettled([slow, fast, fail]).then(results => {
  results.forEach(r => console.log(r.status, r.value ?? r.reason));
});

// race — first to settle wins
Promise.race([slow, fast]).then(v => console.log(v)); // 'fast'

// any — first to FULFILL wins
Promise.any([fail, fast]).then(v => console.log(v));  // 'fast'

Error Handling in Promises

Always attach a .catch() at the end of a promise chain to handle any rejection that bubbles up. The .finally() handler runs regardless of success or failure — useful for cleanup like hiding a loading spinner.

Error Handling
function loadUser(id) {
  return fetch(`/api/users/${id}`)
    .then(res => {
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      return res.json();
    });
}

loadUser(42)
  .then(user => console.log('Loaded:', user.name))
  .catch(err => console.error('Failed:', err.message))
  .finally(() => console.log('Request complete'));
Key Takeaways
  • A Promise has three states: pending, fulfilled, and rejected. Once settled it never changes.
  • .then() handles fulfillment, .catch() handles rejection, .finally() always runs.
  • Promise chains pass return values from one .then() to the next — always return a value or another promise.
  • Promise.all() runs promises in parallel and fails fast if any one rejects.
  • Promise.allSettled() waits for all promises regardless of outcome — use it when you need all results.
  • Always handle rejections with .catch() to avoid unhandled promise rejection warnings.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.