Last week, I spent some time revisiting my NYT Top Stories project from the Vanilla JS Academy. It's a project that uses the Top Stories API to get and display today's top stories from The New York Times.

When I last completed this project, I used the Promise.all() method to fetch stories from multiple categories. But the trouble with this method is that if one promise is rejected, the whole thing fails. Ideally, even if one request fails, I still want to show the data from the others.

Enter the Promise.allSettled() method!

The Promise.allSettled() method accepts an array of promises. It resolves to an array of objects that describes the outcome of each promise.

  • Each object has a status property whose value is either 'fulfilled' or 'rejected'.
  • If the promise was fulfilled, the object has a value property with the resolved value.
  • If the promise was rejected, the object has a reason property with the rejected value.

Here's a simple example of how we might use the Promise.allSettled() method to fetch data from a few different endpoints:

const api = 'https://jsonplaceholder.typicode.com';

// The last endpoint will fail; it should be 'albums'
const endpoints = ['posts', 'comments', 'albutts'];

function getJSON(response) {
if (response.ok) return response.json();

const { status } = response;
const error = new Error(status.toString(10));

return Promise.reject(error);
}

async function getData(endpoint) {
const response = await fetch(`${api}/${endpoint}/1`);
return getJSON(response);
}

const data = endpoints.map(getData);

Promise.allSettled(data).then(results => {
console.log('All results:', results);
});

The data we get back looks something like this:

/*
[
{
status: 'fulfilled',
value: {
userId: number,
id: number,
title: string,
body: string
}
},
{
status: 'fulfilled',
value: {
postId: number,
id: number,
name: string,
body: string
}
},
{
status: 'rejected',
reason: Error
}
]
*/

At this point, we can easily filter out the rejected results using the Array.prototype.filter() method:

function isFulfilled(result) {
return result.status === 'fulfilled';
}

Promise.allSettled(data).then(results => {
console.log('Fulfilled results:', results.filter(isFulfilled));
});

View the demo on CodePen.