Articles

Eine kurze Einführung in „Promises“ und „Async/Await“ (mit neuen Funktionen)

Ein promise ist eine Instanz (Objekt) der Promise Klasse (Konstruktor). Um ein Versprechen zu erstellen, verwenden wir die Syntax new Promise(executor) und stellen eine Executor-Funktion als Argument bereit. Diese Executor-Funktion bietet die Möglichkeit, das Verhalten unserer Promise-Auflösung oder -Ablehnung zu steuern.

In TypeScript können wir den Datentyp des Werts angeben, der zurückgegeben wird, wenn das Versprechen erfüllt wird. Da der vom Versprechen zurückgegebene Fehler jede Form annehmen kann, wird der Standarddatentyp des Werts, der zurückgegeben wird, wenn das Versprechen abgelehnt wird, vom TypeScript auf any .

Um den Auflösungswerttyp des Versprechens zu kommentieren, verwenden wir eine generische Typdeklaration. Grundsätzlich versprechen Sie einen Typ mit Promise Konstruktor in Form von new Promise<Type>() der den aufgelösten Werttyp des Versprechens angibt. Sie können aber auch die Syntax let p: Promise<Type> = new Promise() verwenden, um dasselbe zu erreichen.

💡 Wir haben Generika-Klassen in der Generika-Lektion ausführlich besprochen.

(Versprechen.ts)

Im obigen Beispiel ist findEven ein Versprechen, das mit dem Promise Konstruktor erstellt wurde, der nach 1 Sekunde aufgelöst wird. Der aufgelöste Datentyp dieses Versprechens ist number , daher erlaubt Ihnen der TypeScript-Compiler nicht, resolve aufzurufen Funktion mit einem anderen Wert als einem Wert vom Typ number number.

Der Standardtyp des Ablehnungswerts des Versprechens ist any, daher ist das Aufrufen der reject -Funktion mit einem beliebigen Wert zulässig. Dies ist das Standardverhalten von TypeScript, und Sie können den Diskussionsthread hier finden, wenn Sie Ihre eigene Meinung haben.

Da wir den number als Datentyp für eine erfolgreiche Promise-Auflösung bereitgestellt haben, stellt der TypeScript-Compiler den number -Typ für das Argument der value -Argument der then -Rückrufmethode bereit.

Der in der then -Methode bereitgestellte Rückruf wird ausgeführt, wenn das Versprechen aufgelöst wird, und der in der catch -Methode bereitgestellte Rückruf wird ausgeführt, wenn er abgelehnt wird oder ein Fehler beim Auflösen des Versprechens. Die finally -Methode registriert einen Rückruf, der ausgeführt wird, wenn promise entweder aufgelöst oder abgelehnt wird.

Wenn sich der TypeScript-Compiler über die finally -Methode beschwert, bedeutet dies, dass Ihr TypeScript-Compiler keine Typdefinitionen für die finally -Methode importiert. Diese Methode wurde in ES2016 eingeführt und ist daher ziemlich neu. Stellen Sie daher sicher, dass in Ihrer tsconfig.json -Datei alle neuen Bibliotheken geladen sind.

(tsconfig.json)

In meine tsconfig.json habe ich die ES2020 Standardbibliothek geladen. Dies bietet Unterstützung für alle JavaScript-Funktionen bis ES2020. Wenn Sie mehr über die tsconfig.json -Datei oder Standardbibliotheken erfahren möchten, lesen Sie bitte die Kompilierungsstunde (in Kürze).

Promise Chaining

Die thencatch und finally Methoden geben implizit ein Versprechen zurück. Jeder von diesen Rückruffunktionen zurückgegebene Wert wird mit einem Versprechen umschlossen und zurückgegeben, einschließlich undefined . Dieses implizite Versprechen wird standardmäßig aufgelöst, es sei denn, Sie geben absichtlich ein neues Versprechen von diesen Methoden zurück, das fehlschlagen könnte.

Daher können Sie thencatch oder finally Methoden an eine der vorherigen anhängen thencatch oder finally Methode. Wenn eine implizite Zusage von einer dieser Methoden zurückgegeben wird, ist der aufgelöste Werttyp dieser impliziten Zusage der Typ des zurückgegebenen Werts. Sehen wir uns ein kurzes Beispiel an.

(Versprechen-Verkettung.ts)

Wir haben das vorherige Beispiel modifiziert und der ersten then Methode eine weitere then Methode hinzugefügt. Da die erste then -Methode einen Wert vom Typ string zurückgibt, wird das von dieser Methode zurückgegebene implizite Versprechen mit einem Wert vom Typ string aufgelöst. Daher erhält die zweite then Methode value Argument vom Typ string wie Sie den Ergebnissen entnehmen können.

Versprechen.resolve

Die resolve statische Methode des Promise -Aufrufs gibt ein Versprechen zurück, das bereits erfolgreich mit einem Wert aufgelöst wurde, den Sie im Promise.resolve(value) -Aufruf angeben. Dies ist einfacher, als eine neue Instanz des Versprechensaufrufs zu erstellen und Logik hinzuzufügen, um das Versprechen sofort aufzulösen.

(Versprechen-auflösen.ts)

Wie Sie den obigen Ergebnissen entnehmen können, wird das vom Promise.resolve(value) Aufruf zurückgegebene Versprechen immer sofort mit einem number Wert aufgelöst, da das value Argument den Typ number.

Versprechen.ablehnen

Ähnlich wie Promise.resolve statische Methode gibt die Promise.reject(error) Methode immer ein abgelehntes Versprechen zurück. Der Wert der promise rejection wird aus dem Argument error und sein Typ ist any .

(Versprechen-ablehnen.ts)

Der Typ des Versprechens, das von der Promise.reject Methode zurückgegeben wird, ist Promise<never> da dieses Versprechen niemals aufgelöst wird, gibt es keinen Versprechensauflösungswert. Daher ist der Typ des durch das Versprechen aufgelösten Werts never as never bedeutet den Wert, der niemals auftritt.

Versprechen.all

In einigen Szenarien haben Sie es mit mehreren Versprechen zu tun. Wenn Sie eine Callback-Funktion ausführen möchten, wenn alle Versprechen erfolgreich aufgelöst wurden, verwenden Sie die Promise.all statische Methode.

var pAll = Promise.all()pAll.then( ( ) => {___});

Die Promise.all Methode nimmt ein Array (iterierbar genau) von Versprechen und gibt ein neues Versprechen zurück. Das zurückgegebene Versprechen pAll wird aufgelöst, wenn alle Versprechen p1, p2, ... erfolgreich aufgelöst wurden. Dieses Promise wird mit einem Array-Wert aufgelöst, der die Promise-Auflösungswerte von p1, p2, ... in der Reihenfolge ihres Auftretens enthält.

(Versprechen-alle.ts)

Wie Sie aus dem obigen Beispiel sehen können, Promise.all Methode ist generisch und nimmt den Typ an der Wert, der durch jedes ihm bereitgestellte Versprechen aufgelöst wird. Die Bereitstellung eines generischen Typs ist sehr hilfreich, wenn wir den aufgelösten Wert dieses kollektiven Versprechens verwenden, wie Sie dem obigen Ergebnis entnehmen können.

💡 Die meisten statischen Methoden der Promise -Klasse sind generisch, wie in den folgenden Beispielen gezeigt.

Es gibt eine Einschränkung mit Promise.all. Es implementiert den Fail-Fast-Mechanismus, was bedeutet, wenn eines der Eingangsversprechen p1, p2, ... abgelehnt wird, pAll wird abgelehnt. Wenn nicht warten, bis andere ausstehende Versprechen gelöst sind.

(Versprechen-alle-ablehnen.ts)

Wie Sie dem obigen Ergebnis entnehmen können, wurde das allPromise sofort abgelehnt, da das 3. Versprechen kurz nach 1 Sekunde abgelehnt wurde.

Versprechen.allSettled

Die Promise.allSettled statische Methode ähnelt Promise.all, wartet jedoch im Gegensatz zu Promise.all, bis alle Versprechen erfüllt sind (dh bis sie aufgelöst oder abgelehnt wurden). Daher wird das von Promise.allSettled zurückgegebene Versprechen niemals abgelehnt (aber wir haben den catch -Block im folgenden Beispiel trotzdem hinzugefügt).

(Versprechen-alle-).ts)

Das Arbeiten mit promise.allSettled kann ein wenig überwältigend sein, wie Sie aus dem obigen Programm und seinem Ergebnis entnehmen können. Zuallererst allSettle Methode gibt ein Versprechen zurück, das mit einem Array von PromiseSettledResult<type> Werten aufgelöst wird, wenn alle Versprechen erfüllt sind. Die type wird vom Typ des Eingabepromisses abgeleitet. Der PromiseSettledResult Typ sieht wie folgt aus.

Diese Typen werden von der Standardbibliothek von TypeScript bereitgestellt. Wenn also ein Versprechen aufgelöst wird, allSettled Methode konvertiert seinen Wert in PromiseFulfilledResult Form und wenn es fehlschlägt, konvertiert es es in PromiseRejectedResult Form. Wenn allSettled aufgelöst wird, handelt es sich daher um ein Array von Objekten, in dem jedes Objekt die Form PromiseFulfilledResult oder PromiseRejectedResult hat.

Da PromiseFulfilledResult eine Vereinigung von PromiseFulfilledResult und PromiseRejectedResult ist, die eine gemeinsame status Eigenschaft des literalen Datentyps hat, können wir sie als Diskriminante in der switch/case Wache.

💡 Wir haben über switch/case type guard und diskriminierende Gewerkschaften in der Lektion Type System gesprochen.

(Versprechen-alles-erledigt.ts)

Versprechen.race

Das Promise.race nimmt ein Array (iterierbar genau) von Versprechen und gibt ein neues Versprechen zurück, das aufgelöst oder abgelehnt wird, sobald eines der Eingabeversprechen aufgelöst oder abgelehnt wird. Mit anderen Worten, das von Promise.race zurückgegebene Versprechen wird mit dem Ergebnis eines der Eingabeversprechen abgerechnet, das sich schnell einstellt.

(Versprechen-Rennen.ts)

Im Gegensatz zu Promise.all oder Promise.allSettledgibt diese Methode nur einen einzigen Wert des ersten abgewickelten Versprechens zurück, daher ist der Typ des zurückgegebenen Versprechens im obigen Fall Promise<number>. Da das 1. Versprechen unter anderem zuerst abgerechnet wurde, wird der then Rückruf des fastestPromise nach 500 ms mit dem Wert des aufgelösten Versprechens aufgerufen.

💡 Die neue Promise.any() Methode hat Stufe 4 des ECMAScript Proposal Track erreicht. Promise.any ist ähnlich wie Promise.race aber es wartet, bis das erste Versprechen erfolgreich gelöst ist. Diese Methode löst eine AggregateError Ausnahme aus, wenn alle Versprechen abgelehnt werden.