Anleitung zur Implementierung einer API auf Basis von Promises
Im letzten Artikel haben wir besprochen, wie man APIs verwendet, die Promises zurückgeben. In diesem Artikel betrachten wir die andere Seite — wie man APIs implementiert, die Promises zurückgeben. Dies ist eine weitaus seltenere Aufgabe als die Verwendung von auf Promises basierenden APIs, aber es ist dennoch hilfreich, darüber Bescheid zu wissen.
Voraussetzungen: | Ein solides Verständnis der grundlegenden JavaScript-Konzepte und asynchroner Konzepte, wie sie in den vorherigen Lektionen dieses Moduls behandelt wurden. |
---|---|
Lernziele: | Verstehen, wie man APIs auf Basis von Promises implementiert. |
Im Allgemeinen wird bei der Implementierung einer API auf Basis von Promises eine asynchrone Operation umschlossen, die möglicherweise mit Ereignissen, einfachen Rückruffunktionen (Callbacks) oder einem Nachrichtenübertragungsmodell arbeitet. Sie organisieren ein Promise
-Objekt so, dass es den Erfolg oder das Scheitern dieser Operation korrekt behandelt.
Implementierung einer alarm()
-API
In diesem Beispiel implementieren wir eine API auf Basis von Promises namens alarm()
. Diese Funktion nimmt als Argumente den Namen der Person, die geweckt werden soll, und eine Verzögerung in Millisekunden, bevor die Person geweckt wird. Nach Ablauf der Verzögerung sendet die Funktion eine "Aufwachen!"-Nachricht, die den Namen der Person enthält, die geweckt werden soll.
Umhüllung von setTimeout()
Wir verwenden die setTimeout()
-API, um unsere alarm()
-Funktion zu implementieren. Die setTimeout()
-API nimmt als Argumente eine Rückruffunktion und eine Verzögerung in Millisekunden. Wenn setTimeout()
aufgerufen wird, startet es einen Timer mit der angegebenen Verzögerung. Sobald die Zeit abgelaufen ist, ruft es die angegebene Funktion auf.
Im folgenden Beispiel rufen wir setTimeout()
mit einer Rückruffunktion und einer Verzögerung von 1000 Millisekunden auf:
<button id="set-alarm">Set alarm</button>
<div id="output"></div>
const output = document.querySelector("#output");
const button = document.querySelector("#set-alarm");
function setAlarm() {
setTimeout(() => {
output.textContent = "Wake up!";
}, 1000);
}
button.addEventListener("click", setAlarm);
Der Promise()
-Konstruktor
Unsere alarm()
-Funktion gibt ein Promise
zurück, das erfüllt wird, wenn der Timer abgelaufen ist. Es übergibt eine „Aufwachen!“-Nachricht an den then()
-Handler und lehnt das Promise ab, wenn der Aufrufer einen negativen Wert für die Verzögerung angibt.
Das zentrale Element hierbei ist der Promise()
-Konstruktor. Der Promise()
-Konstruktor nimmt eine einzelne Funktion als Argument, die als executor
bezeichnet wird. Wenn Sie ein neues Promise erstellen, geben Sie die Implementierung des executor
an.
Diese executor
-Funktion selbst nimmt zwei Argumente, die ebenfalls Funktionen sind und konventionell als resolve
und reject
bezeichnet werden. In Ihrer executor
-Implementierung rufen Sie die zugrunde liegende asynchrone Funktion auf. Wenn die asynchrone Funktion erfolgreich ist, rufen Sie resolve
auf, und wenn sie fehlschlägt, rufen Sie reject
auf. Wenn die executor
-Funktion einen Fehler auslöst, wird reject
automatisch aufgerufen. Sie können ein einzelnes Argument beliebigen Typs an resolve
und reject
übergeben.
So können wir alarm()
wie folgt implementieren:
function alarm(person, delay) {
return new Promise((resolve, reject) => {
if (delay < 0) {
reject(new Error("Alarm delay must not be negative"));
return;
}
setTimeout(() => {
resolve(`Wake up, ${person}!`);
}, delay);
});
}
Diese Funktion erstellt und gibt ein neues Promise
zurück. Innerhalb des executor
für das Promise:
-
prüfen wir, ob
delay
nicht negativ ist, und rufenreject
mit einem benutzerdefinierten Fehler auf, falls dies der Fall ist. -
rufen wir
setTimeout()
auf, übergeben einen Callback unddelay
. Der Callback wird aufgerufen, wenn der Timer abläuft, und im Callback rufen wirresolve
auf und übergeben unsere „Aufwachen!“-Nachricht.
Verwendung der alarm()
-API
Dieser Teil sollte Ihnen aus dem letzten Artikel vertraut sein. Wir können alarm()
aufrufen und am zurückgegebenen Promise then()
und catch()
aufrufen, um Handler für das Erfüllen und das Ablehnen der Promises zu setzen.
const name = document.querySelector("#name");
const delay = document.querySelector("#delay");
const button = document.querySelector("#set-alarm");
const output = document.querySelector("#output");
function alarm(person, delay) {
return new Promise((resolve, reject) => {
if (delay < 0) {
reject(new Error("Alarm delay must not be negative"));
return;
}
setTimeout(() => {
resolve(`Wake up, ${person}!`);
}, delay);
});
}
button.addEventListener("click", () => {
alarm(name.value, delay.value)
.then((message) => (output.textContent = message))
.catch((error) => (output.textContent = `Couldn't set alarm: ${error}`));
});
Versuchen Sie, verschiedene Werte für "Name" und "Delay" einzustellen. Probieren Sie, einen negativen Wert für "Delay" zu setzen.
Verwendung von async und await mit der alarm()
-API
Da alarm()
ein Promise
zurückgibt, können wir alles damit machen, was wir auch mit jedem anderen Promise machen können: Promise-Verkettung, Promise.all()
und die Verwendung von async
/ await
:
const name = document.querySelector("#name");
const delay = document.querySelector("#delay");
const button = document.querySelector("#set-alarm");
const output = document.querySelector("#output");
function alarm(person, delay) {
return new Promise((resolve, reject) => {
if (delay < 0) {
reject(new Error("Alarm delay must not be negative"));
return;
}
setTimeout(() => {
resolve(`Wake up, ${person}!`);
}, delay);
});
}
button.addEventListener("click", async () => {
try {
const message = await alarm(name.value, delay.value);
output.textContent = message;
} catch (error) {
output.textContent = `Couldn't set alarm: ${error}`;
}
});