Promises and Async/Await

Promises and async/await are fundamental features for handling asynchronous operations in JavaScript. They provide a cleaner alternative to callback-based approaches.

Promises

// Creating a Promise
const fetchData = new Promise((resolve, reject) => {
  // Simulating API call
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve({ data: 'Success!' });
    } else {
      reject(new Error('Failed to fetch'));
    }
  }, 1000);
});

// Using Promises
fetchData
  .then(result => console.log(result))
  .catch(error => console.error(error))
  .finally(() => console.log('Done'));

Async/Await

// Using async/await
async function getData() {
  try {
    const result = await fetchData;
    console.log(result);
  } catch (error) {
    console.error(error);
  } finally {
    console.log('Done');
  }
}

// Promise methods
const promises = [fetch(url1), fetch(url2), fetch(url3)];

// Parallel execution
const results = await Promise.all(promises);

// Race condition
const firstResult = await Promise.race(promises);

// Handle all settled promises
const settled = await Promise.allSettled(promises);

Key Concepts

  • Promises have three states: pending, fulfilled, rejected
  • async/await is syntactic sugar over Promises
  • Error handling using try/catch with async/await
  • Promise chaining vs async/await sequential execution

Common Interview Follow-up Questions

  1. What's the difference between .then() chains and async/await?
  2. How do you handle multiple async operations in parallel?
  3. What are the benefits of using Promise.allSettled()?
  4. How do you handle errors in Promise chains vs async/await?

Best Practices

  • Always handle Promise rejections
  • Use try/catch blocks with async/await
  • Consider Promise.all() for parallel operations
  • Avoid mixing Promise chains with async/await
  • Remember that async functions always return Promises