Signatur
Beschreibung
Promise.allKeyed() ist das Gegenstück zu Promise.all() für Objekte statt Arrays. Du übergibst ein Objekt, dessen Eigenschaften Promises (oder beliebige Werte) enthalten. Zurück kommt ein Promise, das sich mit einem neuen Objekt erfüllt: Es hat dieselben Schlüssel, aber die Werte sind die aufgelösten Ergebnisse.
Der größte Vorteil ist die Lesbarkeit. Bei Promise.all() musst du auf die Reihenfolge der Array-Positionen achten und die Ergebnisse per Destrukturierung wieder den richtigen Namen zuordnen. Das ist fehleranfällig, wenn Aufrufe ergänzt oder umsortiert werden. Mit allKeyed() bleibt jeder Wert fest an seinen Namen gebunden, etwa { user, posts, settings }.
Das Verhalten entspricht sonst Promise.all(): Alle Promises laufen parallel. Werte, die keine Promises sind, werden wie mit Promise.resolve() behandelt. Sobald ein Promise abgelehnt wird, wird das Ergebnis-Promise sofort mit genau diesem Grund abgelehnt. Wenn du stattdessen alle Ergebnisse unabhängig von Fehlern brauchst, ist Promise.allSettledKeyed() aus demselben Proposal gedacht.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $promises Pflicht | Object | Ein Objekt, dessen eigene aufzählbare Eigenschaften Promises, Thenables oder normale Werte enthalten. Eigenschaften aus der Prototyp-Kette werden ignoriert. Wird kein Objekt übergeben, wird das Promise mit einem TypeError abgelehnt. |
Rückgabewert
Beispiele
Mehrere API-Aufrufe parallel mit sprechenden Namen
const loadDashboard = async (userId) => {
const { user, posts, settings } = await Promise.allKeyed({
user: fetch(`/api/users/${userId}`).then((r) => r.json()),
posts: fetch(`/api/users/${userId}/posts`).then((r) => r.json()),
settings: fetch('/api/settings').then((r) => r.json()),
});
console.log(user.name, posts.length, settings.theme);
};
loadDashboard(42);
Gemischte Werte und Ablehnung
const delay = (ms, value) => new Promise((res) => setTimeout(() => res(value), ms));
const result = await Promise.allKeyed({
a: delay(100, 'A'),
b: 42, // kein Promise, wird direkt übernommen
c: Promise.resolve(true),
});
console.log(result);
try {
await Promise.allKeyed({
ok: delay(50, 'ok'),
fail: Promise.reject(new Error('Timeout')),
});
} catch (err) {
console.log('Fehler:', err.message);
}
Polyfill mit Feature-Erkennung
// Einfache Nachbildung für Umgebungen ohne native Unterstützung
const allKeyed = Promise.allKeyed?.bind(Promise) ?? (async (obj) => {
const keys = Reflect.ownKeys(obj).filter((k) =>
Object.prototype.propertyIsEnumerable.call(obj, k)
);
const values = await Promise.all(keys.map((k) => obj[k]));
return Object.fromEntries(keys.map((k, i) => [k, values[i]]));
});
const config = await allKeyed({
port: Promise.resolve(8080),
host: 'localhost',
});
console.log(config);
// Wichtig · Fallstricke
- Kompatibilität:
Promise.allKeyed()stammt aus dem TC39-Proposal „Await Dictionary“ und ist noch kein fester Teil von ECMAScript. Die meisten Browser und Node.js-Versionen unterstützen es derzeit nicht. Prüfe deshalb vorher mittypeof Promise.allKeyed === 'function'oder verwende einen Polyfill (z. B. core-js). - Fail-fast: Wie bei
Promise.all()führt schon eine einzige Ablehnung dazu, dass das gesamte Ergebnis abgelehnt wird. Die übrigen Promises laufen trotzdem weiter und werden nicht abgebrochen. Zum Abbrechen brauchst du einenAbortController. - Es werden nur eigene aufzählbare Eigenschaften berücksichtigt. Geerbte Eigenschaften und nicht aufzählbare Eigenschaften fallen weg.
- Das Ergebnis ist ein neues Objekt. Details wie der Prototyp des Ergebnisobjekts oder der Umgang mit Symbol-Schlüsseln können sich bis zur endgültigen Standardisierung noch ändern.
- Getter im Eingabeobjekt werden einmal synchron gelesen, und zwar beim Aufruf, nicht erst beim Auflösen der Promises.