© istockphoto.com/lvcandy
TypeScript lernt async/await

Asynchrones TypeScript


In JavaScript sind viele APIs asynchron. Im Gegensatz zu .NET stehen synchrone Funktionen zum Zugriff auf Netzwerk, Datenbanken oder das Dateisystem überhaupt nicht zur Verfügung. Die Folge ist, dass man in JavaScript-Programmen vor lauter Callbacks häufig den eigentlichen Algorithmus nicht mehr sieht. Der Code ist schwer lesbar und fehleranfällig. Frameworks wie Async [1] verbessern die Situation, sind aber gewöhnungsbedürftig. Mit der Version 1.7 hat TypeScript in Sachen asynchrone Funktionen mit C# gleichgezogen: async/await wurde eingeführt. Dieser Artikel zeigt, welche Verbesserungen async/await bringt, wie das Sprachkonstrukt einzusetzen ist und welche Einschränkungen es aktuell gibt.

Video: Typsicheres JavaScript mit TypeScript

Meiner Ansicht nach versteht man Softwareentwicklungskonzepte am besten, wenn man sich klarmacht, welches Problem damit gelöst wird. Lassen Sie uns unsere Reise zu async/await damit beginnen. JavaScript-Entwicklung sowohl am Client als auch am Server hat viel mit asynchroner Programmierung zu tun. Wann immer I/O-Operationen ausgeführt werden sollen, hat man keine andere Wahl, als Funktionen asynchron aufzurufen. Auch wenn die Details sich von Fall zu Fall unterscheiden, das Grundkonzept ist immer das Gleiche: Man gibt im Funktionsaufruf eine Callback-Funktion an, die aufgerufen werden soll, wenn die Operation fertig ist. Das Problem dabei ist, dass die Struktur des Codes aufgrund der Callbacks nicht mehr dem Algorithmus entspricht, den man eigentlich programmieren möchte. Die technische Notwendigkeit der asynchronen Programmierung diktiert die Struktur des Codes. Dadurch wird er schwer zu lesen und zu warten.

Lassen Sie uns dieses Problem zum besseren Verständnis an einem Beispiel betrachten. Angenommen wir möchten den nachfolgenden, einfachen Algorithmus umsetzen:

  • Öffne Verbindung zur Datenbank

  • Lies alle Personen mit Vornamen „John“

  • Iteriere über alle ermittelten Personen

  • Wenn die aktuelle Person ein Kunde ist, lies die Kundendaten und gib Personen- und Kundendaten am Bildschirm aus

  • Wenn die aktuelle Person ein Lieferant ist, lies die Lieferantendaten und gib Personen- und Lieferantendaten am Bildschirm aus

  • Schließe die Datenbankverbindung

Diesen Algorithmus möchten wir mit TypeScript und Node.js programmieren. Als Datenbank verwenden wir exemplarisch MongoDB. (Falls Sie mit dem Code experimentieren wollen, finden Sie ihn auf GitHub [2]) .

Listing 1: Asynchroner Code mit Callbacks

import * as mongodb from 'mongodb'; // Open Database mongodb.MongoClient.connect("mongodb://10.0.75.2:27017/demo", (err, db) => {  // Read all persons with first name "John" db.collection("Person", (err, coll) => { coll.find({ firstName: "John" }).toArray((err, res) => {  // In order to close DB after we are done, we have to use a counter var counter = res.length; var closedb = () => { if (--counter == 0) db.close(); };  // For each person for (var i = 0; i < res.length; i++) { var p = res[i];  // If Person is customer if (p.isCustomer) {  // Read customer details for person db.collection("Customer", (err, custColl) => { custColl.findOne({ id: p.customerId }, (err, cust) => {  // Print person and customer details console.log('John ${p.lastName} works for ${cust.customerName}.');  // Call helper function to close DB if done closedb(); }); }); } else {  // Read supplier details for person db.collection("Supplier", (err, supplColl) => { supplColl.findOne({ id: p.supplierId }, (err, suppl) => {  // Print person and supplier details console.log(''John ${p.lastName} works for ${suppl.supplierName}.');  // Call helper function to close DB if done closedb(); }); }); } } }); }); });

„Callback Hell“

Listing 1 zeigt die Umsetzung unseres Algorithmus mit TypeScript ohne Verwendung von Frameworks wie Async oder async/await. Wie Sie sehen, wird bei jedem MongoDB-Aufruf eine Callback-Funktion angegeben. Der Code wird dadurch schwer verständlich. Man spricht daher auch von der „Callback Hell“. Bedenken Sie, dass unser Beispiel bewusst einfach gehalten ist. Echte Programme in der Praxis sind weitaus komplexer, das Problem wird dadurch noch verschärft. Ganze Webseiten wie etwa unter [3] widmen sich der Frage danach, wie man Code, der Callbacks intensiv verwendet, trotzdem noch halbwegs gut strukturieren kann. Aber auch diese Lösungen sind alles andere als optimal.

Async

Frameworks wie Async bieten Hilfsfunktionen, um der Callback Hell zu entkommen. Statt endlos verschachtelter Callbacks hat man Konstrukte wie async.Waterfall, um eine Sequenz von asynchronen Funktionsaufrufen auszuführen. Es würde den Rahmen dieses Artikels sprengen, wenn wir das Async-Framework hier im Detail beschreiben. Wer sich einen tiefergehenden Überblick über die gebotenen Funktionen verschaffen möchte, findet die Dokumentation unter [1].

Listing 2 zeigt unser Beispiel mit Async. Man sieht, dass der Code dem ei...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang