Skip to content
intermediatePhase 33 · Advanced JavaScript

Promises

Create and chain Promises, handle errors, and use Promise.all/race/allSettled.

1h
0 problems
Topic Progress0%

Creating Promises

A Promise is an object representing the eventual completion or failure of an async operation.

Promise States

  1. Pending: Initial state, neither fulfilled nor rejected
  2. Fulfilled: Operation completed successfully
  3. Rejected: Operation failed

Creating a Promise

const myPromise = new Promise((resolve, reject) => {
  // Perform async operation
  const success = true;
  
  if (success) {
    resolve('Operation completed!'); // Fulfilled
  } else {
    reject(new Error('Something went wrong')); // Rejected
  }
});

// Using the Promise
myPromise
  .then(result => console.log(result))  // 'Operation completed!'
  .catch(error => console.error(error));

Practical Example

function fetchUser(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (userId > 0) {
        resolve({ id: userId, name: 'John' });
      } else {
        reject(new Error('Invalid user ID'));
      }
    }, 1000);
  });
}

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

Immediate Resolution

// Promise.resolve() - creates already fulfilled promise
const resolved = Promise.resolve('done');

// Promise.reject() - creates already rejected promise
const rejected = Promise.reject('error');

Promise Chaining

Promise chaining allows you to perform sequential async operations, avoiding callback hell.

Basic Chaining

fetchUser(1)
  .then(user => {
    console.log('User:', user);
    return fetchPosts(user.id); // Return new promise
  })
  .then(posts => {
    console.log('Posts:', posts);
    return fetchComments(posts[0].id);
  })
  .then(comments => {
    console.log('Comments:', comments);
  })
  .catch(err => {
    console.error('Error in chain:', err);
  });

Key Rules

  1. Each .then() returns a new Promise
  2. The value passed to the next .then() is the resolved value
  3. .catch() handles errors from any previous .then()
  4. Always return promises or values from .then()

Common Mistake

// WRONG - breaking the chain
fetchUser(1)
  .then(user => {
    fetchPosts(user.id); // Missing return!
  })
  .then(posts => {
    console.log(posts); // undefined!
  });

// CORRECT
fetchUser(1)
  .then(user => {
    return fetchPosts(user.id); // Return the promise
  })
  .then(posts => {
    console.log(posts); // Array of posts
  });

Parallel Execution

// Running promises in parallel
Promise.all([
  fetchUser(1),
  fetchUser(2),
  fetchUser(3)
]).then(([user1, user2, user3]) => {
  console.log('All users:', user1, user2, user3);
});

Error Handling

Proper error handling is crucial for robust Promise-based code.

.catch() Method

fetchUser(1)
  .then(user => fetchPosts(user.id))
  .then(posts => processPosts(posts))
  .catch(error => {
    console.error('Error:', error.message);
    // Handle error from any step in the chain
  });

.finally() Method

fetchUser(1)
  .then(user => console.log(user))
  .catch(err => console.error(err))
  .finally(() => {
    console.log('Done!'); // Runs regardless of success/failure
    hideLoadingSpinner();
  });

Error Propagation

function step1() {
  return Promise.resolve('step1');
}

function step2() {
  throw new Error('Error in step2');
}

function step3() {
  return Promise.resolve('step3');
}

step1()
  .then(result => {
    console.log(result); // 'step1'
    return step2();
  })
  .then(result => {
    console.log(result); // Skipped!
    return step3();
  })
  .catch(err => {
    console.error(err); // 'Error in step2'
  });

Handling Multiple Errors

fetchUser(1)
  .then(user => {
    if (!user.name) {
      throw new Error('Missing name');
    }
    return user;
  })
  .catch(error => {
    if (error.message === 'User not found') {
      return defaultUser; // Recover and continue
    }
    throw error; // Re-throw for other errors
  });

Promise Combinators

Promise combinators help manage multiple promises together.

Promise.all()

Resolves when ALL promises resolve. Rejects if ANY rejects.

Promise.all([
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
])
  .then(([users, posts, comments]) => {
    console.log('All data loaded');
  })
  .catch(error => {
    console.error('One request failed:', error);
  });

Promise.allSettled()

Resolves when ALL promises settle (fulfill or reject). Never rejects.

Promise.allSettled([
  Promise.resolve('success'),
  Promise.reject('failure'),
  Promise.resolve('another success')
])
  .then(results => {
    results.forEach(result => {
      if (result.status === 'fulfilled') {
        console.log('Value:', result.value);
      } else {
        console.log('Reason:', result.reason);
      }
    });
  });

Promise.race()

Resolves/rejects with the FIRST settled promise.

Promise.race([
  fetch('/api/fast'),
  fetch('/api/slow'),
  new Promise((_, reject) => 
    setTimeout(() => reject('Timeout'), 5000)
  )
])
  .then(result => {
    console.log('First response:', result);
  })
  .catch(error => {
    console.log('Error or timeout:', error);
  });

Promise.any()

Resolves with the FIRST fulfilled promise. Rejects if ALL reject.

Promise.any([
  fetch('/api/primary'),
  fetch('/api/backup1'),
  fetch('/api/backup2')
])
  .then(result => {
    console.log('Got response from:', result.url);
  })
  .catch(errors => {
    console.log('All failed:', errors);
  });

Practice Problems

0/3solved
Build Promises Component

Create a reusable React component implementing Promises. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Promises Testing

Write unit and integration tests for Promises using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Promises Performance

Optimize Promises for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What are the three states of a Promise?

Question 1 options

2. What does Promise.all() do if one promise rejects?

Question 2 options

3. What is the difference between .catch() and .finally()?

Question 3 options

4. Which combinator never rejects?

Question 4 options

Flashcards

Question

What is a Promise?

Answer

An object representing the eventual completion or failure of an async operation. States: Pending, Fulfilled, Rejected.

Question

What does .then() return?

Answer

A new Promise. If you return a value, it becomes the resolved value. If you return a Promise, the chain waits for it.

Question

Promise.all() vs Promise.allSettled()?

Answer

Promise.all() rejects if any promise rejects. Promise.allSettled() always resolves with status of each promise.

Question

What is Promise.race()?

Answer

Resolves or rejects with the first settled promise. Useful for timeout patterns.

Question

How do you handle errors in promise chains?

Answer

Use .catch() at the end of the chain to handle errors from any previous .then().

Revision Notes

Key Takeaways

  • 1.Promises represent eventual completion or failure of async operations
  • 2.Promise chaining avoids callback hell
  • 3..catch() at the end handles errors from any step
  • 4.Promise.all() is for parallel operations that must all succeed
  • 5.Promise.allSettled() is for when you want all results regardless of success

Interview Tips

  • Know the difference between Promise.all(), allSettled(), race(), and any()
  • Be able to write a Promise chain that properly handles errors
  • Explain how Promises relate to the event loop (microtasks)
  • Discuss when to use Promises vs callbacks vs async/await

Cheat Sheet

Promises Cheat Sheet

States

  • Pending: Initial state
  • Fulfilled: Operation succeeded
  • Rejected: Operation failed

Creating

new Promise((resolve, reject) => {
  if (success) resolve(value);
  else reject(error);
});

Methods

  • .then() - Handle success
  • .catch() - Handle error
  • .finally() - Run regardless

Combinators

  • Promise.all() - All must succeed
  • Promise.allSettled() - Wait for all
  • Promise.race() - First to settle
  • Promise.any() - First to succeed