MWCodebymw.de ↗
JavaScript

Promise.allSettled – wenn ein einziger Fehlschlag nicht alles kippen darf

Promise.all bricht beim ersten Fehler ab und wirft alle anderen Ergebnisse weg. Für ein Dashboard aus fünf Quellen ist das genau falsch: Vier Kacheln könnten Daten zeigen, aber die Seite bleibt leer.

Promise.all ist die richtige Wahl, wenn du alle Ergebnisse brauchst: Fehlt eins, ist die Aufgabe gescheitert. Sobald aber Teilergebnisse wertvoll sind – ein Dashboard, eine Übersicht aus mehreren APIs, ein Import aus vielen Dateien –, ist der Abbruch beim ersten Fehler schädlich.

// Eine kaputte Quelle, und der ganze Aufruf wirft:
const [a, b, c] = await Promise.all([hole('/a'), hole('/b'), hole('/c')]);

allSettled wartet auf alle – und erzählt, wie es ausging

const ergebnisse = await Promise.allSettled([
  hole('/api/wetter'),
  hole('/api/termine'),
  hole('/api/umsatz'),
]);

// [
//   { status: 'fulfilled', value: {...} },
//   { status: 'rejected',  reason: Error('500') },
//   { status: 'fulfilled', value: {...} },
// ]

Die Reihenfolge entspricht immer der Eingabe – auch wenn die dritte Anfrage als erste fertig war.

Ergebnisse und Fehler trennen

const daten   = ergebnisse.filter(e => e.status === 'fulfilled').map(e => e.value);
const fehler  = ergebnisse.filter(e => e.status === 'rejected').map(e => e.reason);

if (fehler.length) {
  console.warn(`${fehler.length} von ${ergebnisse.length} Quellen nicht erreichbar`, fehler);
}
zeigeDashboard(daten);

Wichtig für die Oberfläche: Zeig die Kacheln, die Daten haben, und markier die übrigen ausdrücklich als „gerade nicht erreichbar". Ein leeres Feld ohne Erklärung ist schlimmer als eine ehrliche Meldung.

Mit Namen statt Positionen

Bei mehr als drei Quellen wird das Abzählen über den Index schnell fehleranfällig:

const quellen = { wetter: '/api/wetter', termine: '/api/termine', umsatz: '/api/umsatz' };
const namen   = Object.keys(quellen);
const roh     = await Promise.allSettled(namen.map(n => hole(quellen[n])));

const stand = Object.fromEntries(
  namen.map((n, i) => [n, roh[i].status === 'fulfilled' ? roh[i].value : null])
);

if (stand.umsatz === null) zeigeHinweis('Umsatzzahlen sind gerade nicht verfügbar.');

Die Verwandtschaft in einem Satz

  • Promise.all – alle müssen klappen, bricht beim ersten Fehler ab.
  • Promise.allSettled – wartet auf alle, meldet je Eintrag Erfolg oder Fehler.
  • Promise.any – der erste Erfolg gewinnt, Fehler werden ignoriert (gut für Spiegelserver).
  • Promise.race – das erste Ergebnis gewinnt, egal ob Erfolg oder Fehler (gut für Zeitlimits).

Fallstrick

allSettled lehnt nie ab – und genau deshalb verschluckt es Fehler, wenn du die rejected-Einträge nicht ausliest. Prüfe sie immer, protokolliere sie, und denk daran: Ein fetch, das mit Status 500 antwortet, ist für JavaScript ein erfolgreiches Promise. Wirf im Lade-Helfer selbst, wenn response.ok falsch ist, sonst landen Serverfehler fröhlich im fulfilled-Topf.

Wenn du eine Oberfläche brauchst, die auch mit halb erreichbaren Diensten sauber umgeht: bymw.de.

Quellen

#JavaScript#Promises#Fehlerbehandlung#fetch#async

Du brauchst mehr als ein Snippet?

Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.

Projekt anfragen →