Signatur
Beschreibung
Die statische Methode Promise.race() nimmt ein Iterable von Promises als Eingabe entgegen und gibt ein einzelnes Promise zurück. Dieses zurückgegebene Promise settled mit dem endgültigen Zustand des ersten Promises, das settled.
Die Methode Promise.race() ist eine der Methoden für Promise-Nebenläufigkeit. Sie ist nützlich, wenn du willst, dass die erste asynchrone Aufgabe abgeschlossen wird, dir der endgültige Zustand aber egal ist (d.h. sie kann entweder erfolgreich sein oder fehlschlagen).
Wenn das Iterable einen oder mehrere Nicht-Promise-Werte und/oder ein bereits abgeschlossenes Promise enthält, dann settled Promise.race() zum ersten dieser im Iterable gefundenen Werte.
Wie andere Promise-Kombinatoren markiert Promise.race() alle Promises sofort als „handled", wenn es aufgerufen wird (durch den Aufruf ihrer .then()-Methoden). Nachfolgende Rejections nach dem ersten Settlement werden ignoriert und lösen keine unhandledrejection-Events aus.
Das Settlen des zurückgegebenen Promises bricht die verlierenden Operationen nicht ab und meldet die an ihre Promises angehängten Handler nicht ab. Wenn du wiederholt ein langlebiges, ausstehendes Promise gegen kurzlebige Promises antreten lässt, können sich Handler am ausstehenden Promise auch nach jedem Race-Settlement anhäufen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $iterable Pflicht | Iterable | — | Ein Iterable (wie ein Array) von Promises. Diese Werte werden awaited, sodass andere thenables ebenfalls resolved werden, während Nicht-thenables unverändert zurückgegeben werden. |
Rückgabewert
Promise, das asynchron settled mit dem endgültigen Zustand des ersten Promises im iterable, das settled. Mit anderen Worten: Es fulfillt, wenn das erste settled Promise fulfilled ist, und rejected, wenn das erste settled Promise rejected ist. Das zurückgegebene Promise bleibt für immer pending, wenn das übergebene iterable leer ist. Wenn das übergebene iterable nicht leer ist, aber keine pending Promises enthält, wird das zurückgegebene Promise trotzdem asynchron (statt synchron) settled.Beispiele
Verwendung von Promise.race()
function sleep(time, value, state) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (state === "fulfill") {
resolve(value);
} else {
reject(new Error(value));
}
}, time);
});
}
const p1 = sleep(500, "one", "fulfill");
const p2 = sleep(100, "two", "fulfill");
Promise.race([p1, p2]).then((value) => {
console.log(value); // "two"
// Beide fulfillen, aber p2 ist schneller
});
const p3 = sleep(100, "three", "fulfill");
const p4 = sleep(500, "four", "reject");
Promise.race([p3, p4]).then(
(value) => {
console.log(value); // "three"
// p3 ist schneller, also fulfillt es
},
(error) => {
// Wird nicht aufgerufen
},
);
const p5 = sleep(500, "five", "fulfill");
const p6 = sleep(100, "six", "reject");
Promise.race([p5, p6]).then(
(value) => {
// Wird nicht aufgerufen
},
(error) => {
console.error(error.message); // "six"
// p6 ist schneller, also rejected es
},
);
Asynchronität von Promise.race
// Übergabe eines Arrays von bereits resolveden Promises,
// um Promise.race so schnell wie möglich auszulösen
const resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
const p = Promise.race(resolvedPromisesArray);
// Sofortiges Loggen des Wertes von p
console.log(p);
// Mit setTimeout können wir Code ausführen, nachdem der Stack leer ist
setTimeout(() => {
console.log("the stack is now empty");
console.log(p);
});
// Loggt in dieser Reihenfolge:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: 33 }
Leeres Iterable führt zu dauerhaft pending Promise
const foreverPendingPromise = Promise.race([]);
console.log(foreverPendingPromise);
setTimeout(() => {
console.log("the stack is now empty");
console.log(foreverPendingPromise);
});
// Loggt in dieser Reihenfolge:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "pending" }
Iterable mit bereits settled Werten
const foreverPendingPromise = Promise.race([]);
const alreadyFulfilledProm = Promise.resolve(100);
const arr = [foreverPendingPromise, alreadyFulfilledProm, "non-Promise value"];
const arr2 = [foreverPendingPromise, "non-Promise value", Promise.resolve(100)];
const p = Promise.race(arr);
const p2 = Promise.race(arr2);
console.log(p);
console.log(p2);
setTimeout(() => {
console.log("the stack is now empty");
console.log(p);
console.log(p2);
});
// Loggt in dieser Reihenfolge:
// Promise { <state>: "pending" }
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: 100 }
// Promise { <state>: "fulfilled", <value>: "non-Promise value" }
Verwendung von Promise.race() zur Implementierung eines Request-Timeouts
const data = Promise.race([
fetch("/api"),
new Promise((resolve, reject) => {
// Reject nach 5 Sekunden
setTimeout(() => reject(new Error("Request timed out")), 5000);
}),
])
.then((res) => res.json())
.catch((err) => displayError(err));
Verwendung von Promise.race() zur Erkennung des Status eines Promises
function promiseState(promise) {
const pendingState = { status: "pending" };
return Promise.race([promise, pendingState]).then(
(value) =>
value === pendingState ? value : { status: "fulfilled", value },
(reason) => ({ status: "rejected", reason }),
);
}
Beispielhafte Anwendung von promiseState
const p1 = new Promise((res) => setTimeout(() => res(100), 100));
const p2 = new Promise((res) => setTimeout(() => res(200), 200));
const p3 = new Promise((res, rej) =>
setTimeout(() => rej(new Error("failed")), 100),
);
async function getStates() {
console.log(await promiseState(p1));
console.log(await promiseState(p2));
console.log(await promiseState(p3));
}
console.log("Immediately after initiation:");
getStates();
setTimeout(() => {
console.log("After waiting for 100ms:");
getStates();
}, 100);
// Loggt:
// Immediately after initiation:
// { status: 'pending' }
// { status: 'pending' }
// { status: 'pending' }
// After waiting for 100ms:
// { status: 'fulfilled', value: 100 }
// { status: 'pending' }
// { status: 'rejected', reason: Error: failed }
Vergleich mit Promise.any() — Promise.race
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "one");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, "two");
});
Promise.race([promise1, promise2])
.then((value) => {
console.log("succeeded with value:", value);
})
.catch((reason) => {
// Nur promise1 ist fulfilled, aber promise2 ist schneller
console.error("failed with reason:", reason);
});
// failed with reason: two
Vergleich mit Promise.any() — Promise.any
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "one");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, "two");
});
Promise.any([promise1, promise2])
.then((value) => {
// Nur promise1 ist fulfilled, obwohl promise2 früher settled
console.log("succeeded with value:", value);
})
.catch((reason) => {
console.error("failed with reason:", reason);
});
// succeeded with value: one
// Wichtig · Fallstricke
promiseState läuft weiterhin asynchron, da es keine Möglichkeit gibt, den Wert eines Promises synchron zu erhalten (d.h. ohne then() oder await), selbst wenn es bereits settled ist. promiseState() fulfillt jedoch immer innerhalb eines Ticks und wartet nie tatsächlich auf das Settlement eines Promises.