JavaScript · Async JavaScript

Promises

A Promise represents a value that will be available later — the result of a network request, a timer or a file read.

Intermediate 5 min Lesson 32 of 49 Runnable examples
Before you start:FunctionsError Handling
0/49 in JavaScript
On this page · 5 min · Intermediate

Learning objectives#

  • Describe the three states of a promise
  • Consume promises with then, catch and finally
  • Chain asynchronous steps
  • Run tasks in parallel with Promise.all and Promise.allSettled

Explanation#

A promise starts pending. It then settles exactly once: fulfilled with a value, or rejected with an error.

.then() registers what to do with the value and returns a new promise, which is why calls can be chained. .catch() handles any rejection earlier in the chain. .finally() runs either way.

Promise.all() waits for several promises in parallel and rejects as soon as any one fails. Promise.allSettled() waits for all of them and reports each outcome.

Visual explanation#

A promise starts pending and settles once: fulfilled with a value or rejected with an errorpendingnew Promise(…)resolve(value)reject(error)fulfilled ✓rejected ✕.then(value).catch(error).finally() runseither way
A promise settles exactly once — fulfilled or rejected — and the matching handler runs.

Syntax#

JavaScript Illustrative
const p = new Promise((resolve, reject) => { /* … */ });
p.then(value => …).catch(error => …).finally(() => …);

Code example: Simulating an API call#

JavaScriptSimulating an API call Runnable
function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) resolve({ id, name: 'Asha' });
      else reject(new Error('Invalid user id'));
    }, 300);
  });
}


fetchUser(1)
  .then(user => {
    console.log('Loaded:', user.name);
    return user.id * 10;
  })
  .then(points => console.log('Points:', points))
  .catch(err => console.log('Error:', err.message))
  .finally(() => console.log('Done'));


fetchUser(-1).catch(err => console.log('Error:', err.message));
Expected output
Loaded: Asha
Points: 10
Done
Error: Invalid user id
Opens this example in the full playground

Step-by-step explanation#

  1. fetchUser returns a promise that settles after 300ms.
  2. A positive id resolves with a user object; otherwise it rejects with an Error.
  3. The first then logs the name and returns a number, which becomes the input to the next then.
  4. catch handles a rejection from any earlier step. finally always runs.
  5. The second call rejects, so only its catch runs.

Real-world use case#

fetch() returns a promise. So do most database drivers, file APIs and SDKs, so promises are the foundation of nearly all real-world async JavaScript.

Common mistakes#

Forgetting to return inside then

If you start another async call in then without returning it, the next then runs immediately with undefined.

Unhandled rejections

Every promise chain should end with catch (or be awaited inside try/catch). Unhandled rejections can crash Node.js processes.

Best practices#

  • Always return promises from then callbacks
  • End chains with catch
  • Reject with Error objects, not strings
  • Use Promise.all for independent tasks instead of awaiting them one by one

Remember this#

A promise = a future value: pending → fulfilled or rejected.

.then for success, .catch for errors.

Promise.all waits for many at once.

Practice exercise#

Your task: Use Promise.all to load users 1, 2 and 3 in parallel with fetchUser and log all their names.

Show solution
JavaScript Illustrative
Promise.all([fetchUser(1), fetchUser(2), fetchUser(3)])
  .then(users => console.log(users.map(u => u.name)))
  .catch(err => console.log('One failed:', err.message));

Mini quiz#

Promises quizMultiple choice Question 1 of 2

Which is NOT a promise state?

Score so far: 0/0

Want more? Practise all JavaScript MCQs · JavaScript interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.