Promise.all gives one promise for many, and its failure behaviour is the part that gets assumed rather than read: the first rejection rejects the whole thing immediately, while the other operations keep running with nowhere to report.
// one failure loses the other two results
Promise.all([a(), b(), c()]).then(handle).catch(report);
// settle everything, then decide
Promise.all([a(), b(), c()].map(p =>
p.then(value => ({ ok: true, value }))
.catch(error => ({ ok: false, error }))
)).then(results => { /* every outcome present */ });
The second form is what you want when the operations are independent — three API calls filling three panels, where one failing should not blank the other two. There is no allSettled in the language yet, so the map-and-wrap is the idiom. Note the requests are not cancelled by the rejection either; nothing in this API stops work.