Facebook Pixel

Promise Combinators Best Practices in JavaScript

Promise combinators are powerful. Here are the best practices to use them correctly.

Promise Combinators Best Practices in JavaScript

Promise combinators are powerful. Here are the best practices to use them correctly.

1. Choose the Right Combinator

  • All must succeed: Promise.all.
  • Partial success: Promise.allSettled.
  • First to settle (timeout): Promise.race.
  • First success (ignore failures): Promise.any.

2. Always Handle Errors

try { const [a, b] = await Promise.all([fetchA(), fetchB()]); } catch (err) { handleError(err); } `` ### 3. Use allSettled for Best-Effort Operations ```js const results = await Promise.allSettled([fetchA(), fetchB()]); const successful = results.filter((r) => r.status === "fulfilled").map((r) => r.value); `` ### 4. Clear Timers in Race ```js let timer; try { const result = await Promise.race([ fetch("/api"), new Promise((_, reject) => { timer = setTimeout(() => reject(new Error("timeout")), 5000); }), ]); clearTimeout(timer); } catch (err) { clearTimeout(timer); throw err; } `` ### 5. Use AbortController for Cancellation ```js const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5000); try { const res = await fetch("/api", { signal: controller.signal }); return res; } finally { clearTimeout(timeout); } `` ### 6. Limit Concurrency for Large Sets ```js async function batch(items, size, fn) { for (let i = 0; i < items.length; i += size) { await Promise.all(items.slice(i, i + size).map(fn)); } } `` ### 7. Handle AggregateError with Promise.any ```js try { const result = await Promise.any([fetchA(), fetchB()]); } catch (err) { if (err instanceof AggregateError) { console.error("All failed:", err.errors); } } `` ### 8. Check for Empty Arrays ```js if (promises.length === 0) return []; const results = await Promise.all(promises); `` ### The Takeaway Best practices: choose the right combinator (all for all-must-succeed, allSettled for partial, race for timeout, any for first success), always handle errors, clear timers in race, use AbortController for cancellation, limit concurrency for large sets, handle AggregateError, and check for empty arrays.

Choose the right combinator (all, allSettled, race, any), always handle errors, use allSettled for best-effort, clear timers in race, use AbortController for cancellation, limit concurrency for large sets, handle AggregateError, and check for empty arrays.

Use Promise.all when all operations must succeed (any failure is a total failure). Use Promise.allSettled when you want all results even if some fail (partial success).

Batch items: for (let i = 0; i < items.length; i += size) { await Promise.all(items.slice(i, i + size).map(fn)); }. Process size items at a time to avoid overwhelming the server.

Use try/catch. Check err instanceof AggregateError. Access err.errors (an array of all individual rejection reasons). This lets you see why each promise failed and handle accordingly.

Yes, for fetch. AbortController actually cancels the request (not just races it). Promise.race does not cancel the other promises; they continue running. Use AbortController for real cancellation.

Ready to master React completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.