Baseline Widely available
Der Promise()
-Konstruktor erstellt Promise
-Objekte. Er wird hauptsächlich verwendet, um APIs, die auf Rückrufmethoden basieren und keine Unterstützung für Promises haben, zu erweitern.
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("foo");
}, 300);
});
promise1.then((value) => {
console.log(value);
// Expected output: "foo"
});
console.log(promise1);
// Expected output: [object Promise]
Syntax
Hinweis: Promise()
kann nur mit new
erzeugt werden. Der Versuch, es ohne new
aufzurufen, führt zu einem TypeError
.
executor
Eine function
, die vom Konstruktor ausgeführt wird. Sie erhält zwei Funktionen als Parameter: resolveFunc
und rejectFunc
. Alle im executor
ausgelösten Fehler führen dazu, dass das Promise abgelehnt wird, und der Rückgabewert wird ignoriert. Die Semantik von executor
wird unten detailliert beschrieben.
Bei einem Aufruf über new
gibt der Promise
-Konstruktor ein Promise-Objekt zurück. Das Promise-Objekt wird aufgelöst, wenn eine der Funktionen resolveFunc
oder rejectFunc
aufgerufen wird. Beachten Sie, dass wenn Sie resolveFunc
aufrufen und ein anderes Promise-Objekt als Argument übergeben, das ursprüngliche Promise als "aufgelöst" gilt, aber dennoch nicht "abgeschlossen". Siehe die Promise-Beschreibung für mehr Erklärungen.
Traditionell (vor Promises) wurden asynchrone Aufgaben als Rückrufe entworfen.
readFile("./data.txt", (error, result) => {
// This callback will be called when the task is done, with the
// final `error` or `result`. Any operation dependent on the
// result must be defined within this callback.
});
// Code here is immediately executed after the `readFile` request
// is fired. It does not wait for the callback to be called, hence
// making `readFile` "asynchronous".
Um die Lesbarkeit zu verbessern und die Sprachmerkmale von Promises zu nutzen, ermöglicht der Promise()
-Konstruktor, die auf Rückrufmethoden basierende API in eine Promise-basierte zu transformieren.
Hinweis: Wenn Ihre Aufgabe bereits auf Promises basiert, benötigen Sie den Promise()
-Konstruktor wahrscheinlich nicht.
Der executor
ist maÃgeschneiderter Code, der ein Ergebnis in einem Rückruf mit einem Promise verknüpft. Sie, der Programmierer, schreiben den executor
. Seine Signatur sollte wie folgt aussehen:
function executor(resolveFunc, rejectFunc) {
// Typically, some asynchronous operation that accepts a callback,
// like the `readFile` function above
}
resolveFunc
und rejectFunc
sind ebenfalls Funktionen, und Sie können ihnen beliebige tatsächliche Namen geben. Ihre Signaturen sind einfach: Sie akzeptieren einen einzigen Parameter beliebigen Typs.
resolveFunc(value); // call on resolved
rejectFunc(reason); // call on rejected
Der value
-Parameter, der an resolveFunc
übergeben wird, kann ein weiteres Promise-Objekt sein, in diesem Fall wird der Status des neu erstellten Promises an das übergebene Promise (als Teil des Auflösungs-Promises) "gekoppelt". rejectFunc
hat eine Semantik nahe der throw
-Anweisung, daher ist reason
typischerweise eine Instanz von Error
. Wenn entweder value
oder reason
weggelassen werden, wird das Promise mit undefined
erfüllt/abgelehnt.
Der Abschlusszustand des executor
hat begrenzte Auswirkungen auf den Status des Promises:
executor
wird ignoriert. return
-Anweisungen innerhalb des executor
beeinflussen lediglich den Kontrollfluss und ändern, ob ein Teil der Funktion ausgeführt wird, haben jedoch keinen Einfluss auf den Erfüllungswert des Promises. Wenn executor
endet und es unmöglich ist, dass resolveFunc
oder rejectFunc
in Zukunft aufgerufen werden (zum Beispiel, wenn keine asynchronen Aufgaben geplant sind), bleibt das Promise für immer schwebend.executor
ein Fehler ausgelöst wird, wird das Promise abgelehnt, es sei denn, resolveFunc
oder rejectFunc
wurde bereits aufgerufen.Hinweis: Das Vorhandensein schwebender Promises verhindert nicht, dass das Programm beendet wird. Wenn die Ereignisschleife leer ist, beendet das Programm, trotz aller schwebenden Promises (da diese zwangsläufig für immer schwebend sind).
Hier ein Ãberblick über den typischen Ablauf:
Promise
-Objekt erzeugt, wird auch ein entsprechendes Paar von Funktionen für resolveFunc
und rejectFunc
erzeugt; diese sind mit dem Promise
-Objekt "verbunden".executor
umschlieÃt typischerweise einige asynchrone Vorgänge, die eine auf Rückrufmethoden basierende API bereitstellen. Der Rückruf (derjenige, der an die ursprüngliche Rückruf-basierte API übergeben wird) wird innerhalb des executor
-Codes definiert, sodass er Zugriff auf resolveFunc
und rejectFunc
hat.executor
wird synchron aufgerufen (sobald das Promise
konstruiert ist) mit den resolveFunc
- und rejectFunc
-Funktionen als Argumente.executor
hat die Möglichkeit, eine Operation durchzuführen. Der eventuale Abschluss der asynchronen Aufgabe wird über die Nebenwirkungen, die von resolveFunc
oder rejectFunc
verursacht werden, an die Promise-Instanz kommuniziert. Die Nebenwirkung besteht darin, dass das Promise
-Objekt "aufgelöst" wird.
resolveFunc
zuerst aufgerufen, wird der übergebene Wert aufgelöst. Das Promise kann weiterhin schwebend bleiben (falls ein anderes thenable übergeben wird), erfüllt werden (in den meisten Fällen, in denen ein nicht-thenable Wert übergeben wird) oder abgelehnt werden (bei einem ungültigen Auflösungswert).rejectFunc
zuerst aufgerufen, wird das Promise sofort abgelehnt.resolveFunc
oder rejectFunc
) aufgerufen wird, bleibt das Promise aufgelöst. Nur der erste Aufruf von resolveFunc
oder rejectFunc
beeinflusst den endgültigen Zustand des Promises, und nachfolgende Aufrufe einer der Funktionen können weder den Erfüllungswert/die Ablehnungsursache ändern noch den endgültigen Zustand von "erfüllt" zu "abgelehnt" oder umgekehrt ändern.executor
durch Werfen eines Fehlers beendet wird, wird das Promise abgelehnt. Der Fehler wird jedoch ignoriert, wenn eine der auflösenden Funktionen bereits aufgerufen wurde (so dass das Promise bereits aufgelöst ist).then()
, catch()
oder finally()
damit verbunden sind. Der letztendliche Erfüllungswert oder Ablehnungsgrund wird an die Ausführung der Erfüllungs- und Ablehnungshandler als Eingabeparameter übergeben (siehe Verkettete Promises).Zum Beispiel kann die oben beschriebene Callback-basierte readFile
-API in eine promise-basierte umgewandelt werden.
const readFilePromise = (path) =>
new Promise((resolve, reject) => {
readFile(path, (error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
readFilePromise("./data.txt")
.then((result) => console.log(result))
.catch((error) => console.error("Failed to read data"));
Die resolve
- und reject
-Rückrufe sind nur im Bereich der Executor-Funktion verfügbar, was bedeutet, dass Sie auf sie nicht zugreifen können, nachdem das Promise konstruiert wurde. Wenn Sie das Promise erstellen möchten, bevor Sie entscheiden, wie es aufgelöst wird, können Sie stattdessen die Promise.withResolvers()
-Methode verwenden, die die resolve
- und reject
-Funktionen bereitstellt.
Die resolve
-Funktion hat die folgenden Verhalten:
TypeError
abgelehnt.then
-Eigenschaft nicht aufrufbar ist, einschlieÃlich wenn die Eigenschaft nicht vorhanden ist) aufgerufen, wird das Promise sofort mit diesem Wert erfüllt.Promise
-Instanz) aufgerufen, wird die then
-Methode des Thenables gespeichert und in Zukunft aufgerufen (sie wird immer asynchron aufgerufen). Die then
-Methode wird mit zwei Rückrufen aufgerufen, bei denen es sich um zwei neue Funktionen mit genau demselben Verhalten wie die resolveFunc
und rejectFunc
handelt, die an die executor
-Funktion übergeben werden. Wenn der Aufruf der then
-Methode zu einem Fehler führt, wird das aktuelle Promise mit dem ausgelösten Fehler abgelehnt.Im letzten Fall bedeutet es, dass Code wie folgt ist:
new Promise((resolve, reject) => {
resolve(thenable);
});
Ist ungefähr äquivalent zu:
new Promise((resolve, reject) => {
try {
thenable.then(
(value) => resolve(value),
(reason) => reject(reason),
);
} catch (e) {
reject(e);
}
});
AuÃer dass im Fall von resolve(thenable)
:
resolve
wird synchron aufgerufen, so dass das erneute Aufrufen von resolve
oder reject
keine Wirkung hat, selbst wenn die über anotherPromise.then()
angehängten Handler noch nicht aufgerufen werden.then
-Methode wird asynchron aufgerufen, so dass das Promise niemals sofort aufgelöst wird, wenn ein thenable übergeben wird.Da resolve
erneut mit dem aufgerufen wird, was thenable.then()
ihm als value
übergibt, ist die Rückruffunktion in der Lage, verschachtelte thenables zu glätten, bei denen ein thenable seinen onFulfilled
-Handler mit einem anderen thenable aufruft. Der Effekt ist, dass der Erfüllungs-Handler eines realen Promises niemals ein thenable als seinen Erfüllungswert erhält.
Um einer Funktion Promise-Funktionalität bereitzustellen, lassen Sie sie ein Promise zurückgeben, indem Sie die resolve
- und reject
-Funktionen zur richtigen Zeit aufrufen.
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}
Auswirkung des Aufrufs von resolveFunc
Durch den Aufruf von resolveFunc
wird das Promise aufgelöst, so dass weitere Aufrufe von resolveFunc
oder rejectFunc
keine Wirkung haben. Das Promise kann jedoch in einem der folgenden Zustände sein: schwebend, erfüllt oder abgelehnt.
Dieses pendingResolved
-Promise wird zu dem Zeitpunkt, an dem es erstellt wird, aufgelöst, da es bereits daran "gekoppelt" ist, den eventualen Zustand des inneren Promises zu übernehmen, und der spätere Aufruf von resolveOuter
oder rejectOuter
oder das Werfen eines Fehlers im Executor hat keinen Einfluss auf seinen eventualen Zustand. Das innere Promise ist jedoch noch schwebend, bis 100ms später, so dass das äuÃere Promise ebenfalls schwebend ist:
const pendingResolved = new Promise((resolveOuter, rejectOuter) => {
resolveOuter(
new Promise((resolveInner) => {
setTimeout(() => {
resolveInner("inner");
}, 100);
}),
);
});
Dieses fulfilledResolved
-Promise wird in dem Moment erfüllt, in dem es aufgelöst wird, da es mit einem nicht-thenable Wert aufgelöst wurde. Wenn es erstellt wird, ist es jedoch unaufgelöst, da weder resolve
noch reject
bereits aufgerufen wurden. Ein unaufgelöstes Promise ist zwangsläufig schwebend:
const fulfilledResolved = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("outer");
}, 100);
});
Durch den Aufruf von rejectFunc
wird das Promise offensichtlich abgelehnt. Es gibt jedoch auch zwei Möglichkeiten, das Promise sofort abzulehnen, selbst wenn der resolveFunc
-Rückruf aufgerufen wird.
// 1. Resolving with the promise itself
const rejectedResolved1 = new Promise((resolve) => {
// Note: resolve has to be called asynchronously,
// so that the rejectedResolved1 variable is initialized
setTimeout(() => resolve(rejectedResolved1)); // TypeError: Chaining cycle detected for promise #<Promise>
});
// 2. Resolving with an object which throws when accessing the `then` property
const rejectedResolved2 = new Promise((resolve) => {
resolve({
get then() {
throw new Error("Can't get then property");
},
});
});
Spezifikationen Browser-Kompatibilität Siehe auch
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4