Skip to main content

What is the difference between promise.all and promise.allsettled?

Promise.all rejects the moment any promise in the array rejects. Promise.allSettled always resolves, collecting a result from every promise regardless of whether it succeeded or failed.

Theory

TL;DR

  • Promise.all is like a restaurant order for the whole table: one dish gets cancelled, the entire order is cancelled. Promise.allSettled tracks each dish separately.
  • Promise.all short-circuits on the first rejection and discards the rest.
  • Promise.allSettled always resolves with [{status, value}, {status, reason}, ...].
  • Need every result before moving on? Use all. Need to track all outcomes no matter what? Use allSettled.
  • Both preserve input order, not settle order.

Quick example

javascript
const p1 = Promise.resolve('user data'); const p2 = Promise.reject('DB error'); const p3 = new Promise(resolve => setTimeout(() => resolve('cache data'), 100)); // Bails on p2, p3 result is discarded Promise.all([p1, p2, p3]).catch(err => console.log('all:', err)); // Output: all: DB error // Waits for all three, always resolves Promise.allSettled([p1, p2, p3]).then(results => console.log(results)); // Output: // [ // { status: 'fulfilled', value: 'user data' }, // { status: 'rejected', reason: 'DB error' }, // { status: 'fulfilled', value: 'cache data' } // ]

When p2 rejects, Promise.all stops caring about p3. Promise.allSettled collects all three and resolves normally.

Key difference

Promise.all returns plain values in an array, but only when every promise fulfills. The first rejection triggers the outer promise to reject with that same error. The remaining promises still run to completion, their results are just ignored. Promise.allSettled never rejects. It resolves with an array of objects, each with a status field set to 'fulfilled' or 'rejected', plus either value or reason.

When to use

  • All results are required before moving on (fetching data for every widget on a dashboard): Promise.all
  • Partial failures are acceptable (batch image uploads, sending analytics events): Promise.allSettled
  • You need to log or audit every outcome, including failures: Promise.allSettled
  • Operations depend on each other (need user data before fetching permissions): Promise.all
  • You want to always respond to the client, even when some requests fail: Promise.allSettled

Comparison table

FeaturePromise.allPromise.allSettled
Resolves whenAll promises fulfillAll promises settle
Rejects whenAny promise rejectsNever
Return valueArray of valuesArray of {status, value/reason}
Order preservedYesYes
Empty array inputResolves []Resolves []
Non-promise valuesTreated as resolvedTreated as resolved
Typical use caseCritical batch operationsHealth checks, bulk uploads

How it works internally

Both methods iterate the input and track a counter of pending promises. Promise.all attaches a single rejection handler that fires on the first failure and ignores everything else. Promise.allSettled attaches both .then() and .catch() to each promise individually, pushing a status object to the results array on every settle. When the counter hits zero, the outer promise resolves with the full array. Both follow the same spec since ES2020 and are available from Node.js 12.9+.

Common mistakes

Expecting Promise.all to give partial results

javascript
// Wrong: .then() never fires if rejectingP rejects Promise.all([p1, rejectingP, p3]) .then(results => console.log(results)); // Fix: switch to allSettled and filter Promise.allSettled([p1, rejectingP, p3]) .then(results => results .filter(r => r.status === 'fulfilled') .map(r => r.value) );

Forgetting that allSettled wraps results in objects

javascript
// Wrong: result is an object, not the actual value for (const result of await Promise.allSettled(promises)) { processData(result); // passes {status, value} instead of the data } // Fix: check status before accessing the value for (const result of await Promise.allSettled(promises)) { if (result.status === 'fulfilled') processData(result.value); else logError(result.reason); }

Using allSettled when operations depend on each other

javascript
// Wrong: continues with undefined if fetchUser fails const results = await Promise.allSettled([fetchUser(id), fetchPermissions(id)]); const user = results[0].value; // undefined if rejected renderDashboard(user); // crashes // Fix: for dependent data, use Promise.all const [user, permissions] = await Promise.all([fetchUser(id), fetchPermissions(id)]);

Passing non-promise values without knowing the behavior

javascript
// Works, but mixing types hides intent Promise.all([1, 'hello', fetch('/api/data')]); // 1 and 'hello' become Promise.resolve(1) and Promise.resolve('hello') // Be explicit about what you're running concurrently

Real-world usage

  • React Query: useQueries uses allSettled internally so each query has its own loading and error state
  • Next.js: getStaticPaths fallback logic during build-time uses allSettled
  • Express batch endpoints: allSettled to always send a response, even when some DB queries fail
  • Puppeteer: allSettled for page scraping when some selectors may not exist on every page
  • Node.js CLI tools: allSettled for bulk file reads where some files might be missing

Follow-up questions

Q: What happens when you pass an empty array to either method?
A: Both resolve immediately with []. No rejection, no waiting.

Q: What if the array contains a plain value like a number instead of a promise?
A: Both coerce it to Promise.resolve(value). With allSettled, it shows as {status: 'fulfilled', value: number}.

Q: Does the output order match the input order?
A: Yes, always. The order reflects the input array, not which promise settled first.

Q: How does Promise.any() differ from these two?
A: Promise.any() resolves as soon as the first promise fulfills and rejects only if every promise rejects. Promise.allSettled always waits for everything and never rejects.

Q (senior): How would you polyfill Promise.allSettled for environments without native support?
A: Wrap each promise with .then(value => ({status: 'fulfilled', value})).catch(reason => ({status: 'rejected', reason})), then pass the array to Promise.all. Each wrapper always fulfills, so Promise.all never rejects and you get back the same shape as allSettled.

Examples

Fetching data for multiple API endpoints

javascript
const userIds = [1, 2, 3]; try { const users = await Promise.all( userIds.map(id => fetch(`/api/users/${id}`).then(r => r.json())) ); console.log(users); // [user1, user2, user3] } catch (err) { // One fetch failed, nothing rendered console.error('Fetch failed:', err); }

Use this when all data is required before rendering. If user 2 is missing, showing the others could mislead the user about what data is actually available.

Express batch endpoint with partial success

javascript
app.get('/batch/users', async (req, res) => { const ids = req.query.ids.split(','); const results = await Promise.allSettled( ids.map(id => fetchUserFromDB(id)) ); const found = results .filter(r => r.status === 'fulfilled') .map(r => r.value); const failed = results .filter(r => r.status === 'rejected') .map((r, i) => ({ id: ids[i], error: r.reason.message })); res.json({ found, failed }); // Always responds, even when some DB queries fail });

The client always gets a response and knows exactly which IDs worked and which did not. This pattern comes up often in admin tools and batch-action APIs.

Bulk file reads with error tracking

javascript
const fs = require('fs').promises; const filePaths = ['./data/a.json', './data/b.json', './data/missing.json']; const results = await Promise.allSettled( filePaths.map(path => fs.readFile(path, 'utf-8').then(JSON.parse)) ); results.forEach((result, i) => { if (result.status === 'fulfilled') { console.log(`Loaded ${filePaths[i]}:`, result.value); } else { console.warn(`Skipped ${filePaths[i]}:`, result.reason.message); } }); // Processes a.json and b.json, logs a warning for missing.json

I've used this in data migration scripts where some source files are optional. With Promise.all, a single missing file would abort the entire run. Promise.allSettled processes everything it can and tells you what failed.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?