Promise.race()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Die statische Methode Promise.race()
nimmt ein iterierbares Objekt von Promises als Eingabe und gibt ein einzelnes Promise
zurück. Dieses zurückgegebene Promise übernimmt den endgültigen Status des ersten Promise, das abgeschlossen wird.
Probieren Sie es aus
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "one");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "two");
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster
});
// Expected output: "two"
Syntax
Promise.race(iterable)
Parameter
iterable
-
Ein iterierbares Objekt (wie ein
Array
) von Promises.
Rückgabewert
Ein Promise
, das asynchron abgeschlossen wird mit dem endgültigen Status des ersten Promises im iterable
, das sich abschließt. Das bedeutet, es wird erfüllt, wenn das erste Promise, das sich schließt, erfüllt ist, und abgelehnt, wenn das erste Promise, das sich schließt, abgelehnt wird. Das zurückgegebene Promise bleibt für immer ausstehend, wenn das übergebene iterable
leer ist. Wenn das übergebene iterable
nicht leer ist, aber keine ausstehenden Promises enthält, wird das zurückgegebene Promise trotzdem asynchron (statt synchron) abgeschlossen.
Beschreibung
Die Promise.race()
-Methode ist eine der Methoden für Promise-Konkurrenz. Sie ist nützlich, wenn Sie die erste asynchrone Aufgabe beenden möchten, sich jedoch nicht um deren endgültigen Status kümmern (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, wird Promise.race()
mit dem ersten dieser im iterable
gefundenen Werte abgeschlossen.
Beispiele
Verwendung von Promise.race()
Dieses Beispiel zeigt, wie Promise.race()
verwendet werden kann, um mehrere Timer, die mit setTimeout()
implementiert sind, gegeneinander antreten zu lassen. Der Timer mit der kürzesten Dauer gewinnt immer das Rennen und bestimmt den Zustand des resultierenden Promises.
function sleep(time, value, state) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (state === "fulfill") {
return resolve(value);
} else {
return 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"
// Both fulfill, but p2 is faster
});
const p3 = sleep(100, "three", "fulfill");
const p4 = sleep(500, "four", "reject");
Promise.race([p3, p4]).then(
(value) => {
console.log(value); // "three"
// p3 is faster, so it fulfills
},
(error) => {
// Not called
},
);
const p5 = sleep(500, "five", "fulfill");
const p6 = sleep(100, "six", "reject");
Promise.race([p5, p6]).then(
(value) => {
// Not called
},
(error) => {
console.error(error.message); // "six"
// p6 is faster, so it rejects
},
);
Asynchronität von Promise.race
Das folgende Beispiel zeigt die Asynchronität von Promise.race
. Im Gegensatz zu anderen Methoden für Promise-Konkurrenz ist Promise.race
immer asynchron: Es wird nie synchron abgeschlossen, selbst wenn das iterable
leer ist.
// Passing an array of promises that are already resolved,
// to trigger Promise.race as soon as possible
const resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
const p = Promise.race(resolvedPromisesArray);
// Immediately logging the value of p
console.log(p);
// Using setTimeout, we can execute code after the stack is empty
setTimeout(() => {
console.log("the stack is now empty");
console.log(p);
});
// Logs, in order:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: 33 }
Ein leeres iterable
bewirkt, dass das zurückgegebene Promise für immer ausstehend bleibt:
const foreverPendingPromise = Promise.race([]);
console.log(foreverPendingPromise);
setTimeout(() => {
console.log("the stack is now empty");
console.log(foreverPendingPromise);
});
// Logs, in order:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "pending" }
Wenn das iterable
einen oder mehrere Nicht-Promise-Werte und/oder ein bereits abgeschlossenes Promise enthält, wird Promise.race
mit dem ersten dieser im Array gefundenen Werte abgeschlossen:
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);
});
// Logs, in order:
// 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 Anfrage-Timeouts
Sie können eine möglicherweise lang andauernde Anfrage mit einem Timer, der ablehnt, konkurrieren lassen, sodass das resultierende Promise automatisch abgelehnt wird, wenn die Zeit abgelaufen ist.
const data = Promise.race([
fetch("/api"),
new Promise((resolve, reject) => {
// Reject after 5 seconds
setTimeout(() => reject(new Error("Request timed out")), 5000);
}),
])
.then((res) => res.json())
.catch((err) => displayError(err));
Wenn das data
-Promise erfüllt wird, enthält es die von /api
abgerufenen Daten; andernfalls wird es abgelehnt, wenn fetch
für 5 Sekunden ausstehend bleibt und gegen den setTimeout
-Timer verliert.
Verwendung von Promise.race() zur Erkennung des Status eines Promises
Da Promise.race()
auf das erste nicht ausstehende Promise im iterable
reagiert, können wir den Status eines Promises überprüfen, einschließlich ob es ausstehend ist. Dieses Beispiel wurde aus promise-status-async
adaptiert.
function promiseState(promise) {
const pendingState = { status: "pending" };
return Promise.race([promise, pendingState]).then(
(value) =>
value === pendingState ? value : { status: "fulfilled", value },
(reason) => ({ status: "rejected", reason }),
);
}
In dieser Funktion, wenn promise
ausstehend ist, wird der zweite Wert, pendingState
, welcher ein Nicht-Promise ist, das Ergebnis des Rennens; andernfalls, wenn promise
bereits abgeschlossen ist, können wir seinen Status über die onFulfilled
- und onRejected
-Handler erkennen. Zum Beispiel:
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(300), 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);
// Logs:
// Immediately after initiation:
// { status: 'pending' }
// { status: 'pending' }
// { status: 'pending' }
// After waiting for 100ms:
// { status: 'fulfilled', value: 100 }
// { status: 'pending' }
// { status: 'rejected', reason: 300 }
Hinweis:
Die Funktion promiseState
läuft weiterhin asynchron, da es keinen Weg gibt, den Wert eines Promises synchron zu erhalten (z.B. ohne then()
oder await
), selbst wenn es bereits abgeschlossen ist. promiseState()
wird jedoch immer innerhalb eines Ticks erfüllt und wartet tatsächlich niemals auf die Erledigung eines Promises.
Vergleich mit Promise.any()
Promise.race
nimmt das erste abgeschlossene Promise
.
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) => {
// Only promise1 is fulfilled, but promise2 is faster
console.error("failed with reason:", reason);
});
// failed with reason: two
Promise.any
nimmt das erste erfüllte Promise
.
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) => {
// Only promise1 is fulfilled, even though promise2 settled sooner
console.log("succeeded with value:", value);
})
.catch((reason) => {
console.error("failed with reason:", reason);
});
// succeeded with value: one
Spezifikationen
Specification |
---|
ECMAScript® 2025 Language Specification # sec-promise.race |
Browser-Kompatibilität
Report problems with this compatibility data on GitHubdesktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
race() |
Legend
Tip: you can click/tap on a cell for more information.
- Full support
- Full support