What's the difference between Promise.all(), Promise.race(), Promise.allSettled(), and Promise.any()? When would you use each?

3 minintermediatejavascriptdifferencepromise.allpromise.racepromise.allsettled

Quick Answer

These are different Promise combinator methods that handle multiple promises in various ways.

Detailed Answer

What's the difference between Promise.all(), Promise.race(), Promise.allSettled(), and Promise.any()? When would you use each?

Answer: These are different Promise combinator methods that handle multiple promises in various ways:

Promise.all():

  • Waits for ALL promises to resolve
  • Fails fast - rejects if ANY promise rejects
  • Returns array of resolved values in same order
  • Use when: You need all operations to succeed
const promises = [
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
];

try {
  const [users, posts, comments] = await Promise.all(promises);
  // All requests succeeded
} catch (error) {
  // At least one request failed
  console.error('One or more requests failed:', error);
}

Promise.race():

  • Returns the FIRST promise to settle (resolve or reject)
  • Use when: You want the fastest result, regardless of success/failure
const timeoutPromise = new Promise((_, reject) => 
  setTimeout(() => reject(new Error('Timeout')), 5000)
);

const dataPromise = fetch('/api/slow-endpoint');

try {
  const result = await Promise.race([dataPromise, timeoutPromise]);
  // Got data before timeout
} catch (error) {
  // Either timeout or request failed
  console.error('Request failed or timed out:', error);
}

Promise.allSettled():

  • Waits for ALL promises to settle (resolve or reject)
  • Never rejects - always resolves with array of results
  • Use when: You want to know the outcome of all operations
const promises = [
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
];

const results = await Promise.allSettled(promises);

results.forEach((result, index) => {
  if (result.status === 'fulfilled') {
    console.log(`Request ${index} succeeded:`, result.value);
  } else {
    console.log(`Request ${index} failed:`, result.reason);
  }
});

Promise.any():

  • Returns the FIRST promise to resolve (ignores rejections)
  • Only rejects if ALL promises reject
  • Use when: You want the first successful result
const fallbackPromises = [
  fetch('/api/primary'),
  fetch('/api/backup1'),
  fetch('/api/backup2')
];

try {
  const result = await Promise.any(fallbackPromises);
  // Got data from first successful endpoint
} catch (error) {
  // All endpoints failed
  console.error('All endpoints failed:', error);
}

Coding Challenge: Implement a function that retries a failed async operation with exponential backoff.

Answer:

async function retryWithBackoff(
  asyncFn, 
  maxRetries = 3, 
  baseDelay = 1000, 
  maxDelay = 10000
) {
  let lastError;
  
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await asyncFn();
    } catch (error) {
      lastError = error;
      
      if (attempt === maxRetries) {
        throw new Error(`Failed after ${maxRetries + 1} attempts: ${error.message}`);
      }
      
      // Calculate delay with exponential backoff and jitter
      const delay = Math.min(
        baseDelay * Math.pow(2, attempt) + Math.random() * 1000,
        maxDelay
      );
      
      console.log(`Attempt ${attempt + 1} failed, retrying in ${Math.round(delay)}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Usage example
async function fetchUserData(userId) {
  const response = await fetch(`/api/users/${userId}`);
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }
  return response.json();
}

// Retry with custom configuration
try {
  const userData = await retryWithBackoff(
    () => fetchUserData(123),
    5,    // max retries
    1000, // base delay (1s)
    30000 // max delay (30s)
  );
  console.log('User data:', userData);
} catch (error) {
  console.error('Failed to fetch user data:', error);
}

// Advanced version with different retry strategies
class RetryStrategy {
  static async exponentialBackoff(asyncFn, options = {}) {
    const {
      maxRetries = 3,
      baseDelay = 1000,
      maxDelay = 10000,
      jitter = true,
      retryCondition = () => true
    } = options;
    
    let lastError;
    
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        return await asyncFn();
      } catch (error) {
        lastError = error;
        
        if (attempt === maxRetries || !retryCondition(error)) {
          throw error;
        }
        
        const delay = Math.min(
          baseDelay * Math.pow(2, attempt) + (jitter ? Math.random() * 1000 : 0),
          maxDelay
        );
        
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
  }
  
  static async linearBackoff(asyncFn, options = {}) {
    const { maxRetries = 3, delay = 1000 } = options;
    
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        return await asyncFn();
      } catch (error) {
        if (attempt === maxRetries) throw error;
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
  }
}