0Pricing
Frontend Academy · Lesson

Promises: then catch finally Promise.all

Create and chain Promises, handle errors in catch blocks, run cleanup in finally, and run multiple Promises in parallel with Promise.all.

Promises: then catch finally Promise.all is a free Frontend Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is a Promise?

A Promise represents a value that will be available in the future. It's an object in one of three states: pending (initial), fulfilled (resolved with a value), or rejected (failed with a reason). Once settled, a Promise's state is permanent.

Creating a Promise

Create a Promise with the new Promise(executor) constructor. The executor function receives resolve and reject callbacks. Call resolve with the success value or reject with an error.

const delay = (ms) => new Promise((resolve) => {
  setTimeout(resolve, ms);
});

const fetchData = (url) => new Promise((resolve, reject) => {
  fetch(url)
    .then(res => res.json())
    .then(resolve)
    .catch(reject);
});

.then() — Handling Success

promise.then(onFulfilled) registers a callback that runs when the Promise fulfils. It receives the resolved value. .then() returns a new Promise, enabling chaining.

fetch('/api/users')
  .then(response => response.json())
  .then(users => {
    console.log('Users:', users);
    return users.length;
  })
  .then(count => console.log('Count:', count));

.catch() — Handling Errors

promise.catch(onRejected) handles rejections. Placed at the end of a chain, it catches any error from any step above it.

fetch('/api/data')
  .then(res => {
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
  })
  .then(data => processData(data))
  .catch(err => {
    console.error('Failed:', err.message);
    showErrorToUser();
  });

.finally() — Always Run

promise.finally(onFinally) runs whether the Promise fulfilled or rejected. Perfect for cleanup: hiding a loading spinner, releasing a lock, logging analytics.

showSpinner();
fetch('/api/data')
  .then(res => res.json())
  .then(render)
  .catch(handleError)
  .finally(() => hideSpinner()); // always runs

Promise Chaining — Returning Values

Return a value from .then() and it becomes the resolved value of the next .then(). Return a new Promise to chain async operations sequentially.

getUser(id)
  .then(user => getOrders(user.id))  // return Promise
  .then(orders => orders[0])          // return value
  .then(order => console.log(order)); // receive order

Promise.all() — Run in Parallel

Promise.all([p1, p2, p3]) waits for all promises to resolve and returns an array of results in the same order. If any promise rejects, the whole thing rejects immediately.

const [user, posts, comments] = await Promise.all([
  fetch('/api/user/1').then(r => r.json()),
  fetch('/api/posts').then(r => r.json()),
  fetch('/api/comments').then(r => r.json()),
]);
// All three run in parallel — much faster than sequential

Promise.allSettled() — Don't Fail Fast

Promise.allSettled() waits for all promises to settle (resolve or reject) and returns an array of result objects with {status, value} or {status, reason}. Useful when you don't want one failure to kill all results.

const results = await Promise.allSettled([p1, p2, p3]);
results.forEach(result => {
  if (result.status === 'fulfilled') use(result.value);
  else logError(result.reason);
});

Promise.race() and Promise.any()

Promise.race() resolves/rejects with the first settled promise. Promise.any() resolves with the first fulfilled promise (ignores rejections; rejects only if all reject). Useful for timeouts and redundancy.

// Timeout pattern:
const withTimeout = (promise, ms) => Promise.race([
  promise,
  new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms))
]);

Creating Already-Settled Promises

Promise.resolve(value) creates a Promise already fulfilled with value. Promise.reject(error) creates an already-rejected Promise. Useful for testing and adapter functions.

const p = Promise.resolve(42);
p.then(v => console.log(v)); // 42

Unhandled Rejection Events

If a Promise rejects with no .catch(), it becomes an unhandled rejection. Modern browsers and Node.js emit warnings. Always attach a .catch() or use try/catch with async/await.

window.addEventListener('unhandledrejection', event => {
  console.error('Unhandled rejection:', event.reason);
  event.preventDefault();
});

Quick Check

Which static method runs multiple promises in parallel and resolves with an array of all results?

Recap: Promises

.then() for success, .catch() for errors, .finally() for cleanup. Chains pass values through. Promise.all() parallelises. Promise.allSettled() tolerates partial failure. Promise.race() for the fastest result. Always handle rejections. Modern code uses async/await as syntactic sugar over Promises.

Frequently asked questions

Is the “Promises: then catch finally Promise.all” lesson free?

Yes — the full text of “Promises: then catch finally Promise.all” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.

What will I learn in “Promises: then catch finally Promise.all”?

Create and chain Promises, handle errors in catch blocks, run cleanup in finally, and run multiple Promises in parallel with Promise.all. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Frontend Academy?

No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Promises: then catch finally Promise.all” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Frontend Academy lesson?

Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. The Event Loop: Call Stack Queue Microtasks
  2. Callbacks and Callback Hell
  3. Promises: then catch finally Promise.all
  4. async/await and Error Handling
← Back to Frontend Academy