JavaScript: Asynchrone Programmierung

Kriterien für asynchrone Lösungen

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Asynchrone Lösungsansätze sollen Ihnen das Leben als Entwickler vereinfachen. Daher gilt es eine Erwartungshaltung zu definieren, was eine solche Lösung idealerweise erfüllen kann.

Transkript

Das Auflösen der Komplexitäten bei Asynchronität, ist eine Problemstellung, die fast so alt ist wie die JavaScript selbst Da es nun also bereits diverse Ansätze zu dieser Problematik gibt, möchte ich innerhalb des Videos mit Ihnen Kriterien und Anforderungen diskutieren, anhand derer man diese Art von Lösungen beurteilen kann. Das Ganze möchte ich Ihnen nun anhand von Pseudo-Code demonstrieren. Für diesen Zweck lege ich eine nue JavaScript Datei an, mit der Bezeichnung: 03_criteria.js. Als Beispiel betrachten wir also nun den Aufruf einer Web API. Dafür verwende ich das Paket request für NodeJS. Eine klassische Benutzung dieser request API sieht nun also vor, dass wir eine URL als Parameter übergeben, und über einen Callback darüber informiert werden, was tatsächlich nun das Resultat dieses Webaufrufes ist. Das erste Kriterium ist nun also die Intuitivität dieses Aufrufes. Beim Aufruf von request, muss ich also einen zweiten Parameter mitgeben, der hier eine Funktion repräsentiert. In anderen Programmiersprachen, die in diesem Moment die Anwendung blockieren und auf das Resultat warten würden, habe ich diese Problematik nicht. Das bedeutet, dass ich hier intuitiv meinen Code so schreiben würde, dass ich beispielsweise ein Resultat Objekt bekomme, vom Aufruf auf request. Wenn ich nun etwas mehr Code schreibe, der beispielsweise mit dem Resultat dieses Aufrufs weiterarbeitet, also wie in diesem Fall JSON.parse, res.body, hätte ich quasi hier nun meine Nummer aus dieser Abfrage bekommen. Klassischerweise würde aber der Code an dieser Stelle nun stehenbleiben müssen, da ohne das Resultat res, die JSON.parse Funktion nicht arbeiten kann. Nach Prinzipien einer blockierenden Programmiersprache wie Java, würde das bedeuten, dass unser Thread an dieser Stelle nun stehen bleibt, und effektiv warten muss, bis tatsächlich diese Antwort zurückgekommen ist. Selbstverständlich sollte aus Gründen der Effizienz, da wir in JavaScript nur einen einzige Thread haben, diese Situation niemals eintreten. Das heißt, wenn wir diese Möglichkeiten bekommen, unseren Aufruf so ausdrucksfähig und intuitiv wie möglich zu gestalten, sollte eine Lösung dafür sorgen, dass wir uns nicht darum kümmern müssen, dass unsere Anwendung zu diesem Zeitpunkt stehen bleibt. Für die Ausdrucksfähigkeit ist allerdings auch wichtig, dass wir erkennen können, dass unser Code, nach diesem Aufruf auf request, nicht sofort ausgeführt wird. Das bedeutet, idealerweise sind wir in der Lage, nun diese Zeile zu markieren, und dadurch darzustellen, dass dieser Aufruf asynchron ist. Beispielweise mit call. Selbstverständlich gibt es diesen Ausdruck nicht und mittlerweile mit dem ES2017 Standard, hat sich hier eingebürgert, das keyword await. Ähnlich wie in den Programmiersprachen C# und Python. Dadurch, dass wir nun auch einen geraden Kontrollfluss haben, also hier alle Aufrufe nacheinander stattfinden, haben wir nicht mehr das Problem, dass innerhalb einer solchen Funktion, seitenbehaftete Effekte auf Variablen auftreten können, die außerhalb der Funktion stehen. Im Überblick heißt das nun also, das wichtigste Kriterium einer solchen Lösung für das Asynchronitätsproblem ist die Intuitivität. Außerdem müssen wir dabei ausdrucksfähig bleiben und immer erkennen können, dass es sich hierbei um einen asynchronen Aufruf handelt. Seitenbehaftete Effekte sollten also vermieden werden, und die Effizienz, also nicht das Anhalten unseres Programms, steht dabei im Vordergrund. Da nun, egal welche Art von Lösung wir bauen, es im Hintergrund trotzdem über Callbacks, also Funktionen gelöst werden muss sollten wir einige funktionale Anforderungen an diese Konstrukte stellen. Auch für funktionale Anforderungen möchte ich das Ganze mit Pseudocode illustrieren. Stellen wir uns also vor, wir haben einen Kunden, der den Warenkorb bestellt. Nennen wir also diese Funktion nun warenkorbbestellen. Außerdem haben wir eine Funktion, die geldabbuchen heißt. In einer asynchronen Welt, würden wir also nun die Möglichkeit nutzen, den Warenkorb zu bestellen. In dem Moment, wo der Warenkorb bestellt ist, soll also das Geld abgebucht werden. Das heißt, der Aufruf geldabbuchen ist abhängig davon, dass wir den Warenkorb bestellt haben. Was passiert nun aber, wenn wir innerhalb von warenkorbbestellen, beispielsweise einen Vorgang haben, der durch alle Produkte im Warenkorb durchgeht, und bestimmte Aktionen durchführt, wie den Warenwert zusammenzuzählen. Stellen wir uns nun vor, dass der Warenwert zusammengezählt ist, und wir beim letzten Produkt sind, aber immer noch innerhalb des Loops. Und wir haben hier beispielsweise eine Art Programmierfehler hinzugefügt. Dann kann es passieren, dass wenn wir die Funktion geldabbuchen, als Parameter bekommen, wir diese Funktion nun mehrfach ausführen. Mehrfach ausführen bedeutet also für den Kunden, dass wir ihm mehrfach Geld abbuchen werden. Indem wir nun die geldabbuchen Funktion als Parameter übergeben haben, haben wir einer anderen Funktion, die Kontrolle darüber gegeben, unsere eigene Funktion nach Belieben oft auszuführen. Je nachdem, wie diese Funktion warenkorbbestellen programmiert ist, kann es ein Fehler sein, dass die Funktion geldabbuchen mehrfach aufgerufen wird. Und dadurch können unerwartete Systemzustände auftreten. Außerdem garantiert uns warenkorbbestellen nicht wirklich, zu welchem Zeitpunkt geldabbuchen nun aufgerufen wird. Beispielsweise könnte warenkorbbestellen, nun auch das Geld abbuchen, bevor der Warenwert überhaupt korrekt zusammengezählt wurde. Auch das wäre für unsere Funktion geldabbuchen ein unerwünschtes Verhalten. Wenn auch das Ganze sehr offensichtlich wirkt, gibt es diese Garantien oft nicht, und gerade immer dann wenn man eine Funktion aufruft, deren Inhalt man nicht kontrolliert, beispielweise bei anderen Bibliotheken, ist man immer abhängig von deren Implementierung. Dazu gehört auch die Möglichkeit, dass der Kontext von meiner geldabbuchen Funktion verschoben wird. Beispielsweise würde ich annehmen, dass ich auf das Konto Zugriff habe, über den Aufruf von this. Allerdings kann die warenkorbbestellen Funktion, die Präferenz auf this, durch beispielsweise das Ersetzen mit null, neu binden. Das kann aus den verschiedensten Gründen innerhalb der Funktion passieren. Und auch diese Art von Zustand muss vermieden werden. Der letzte, aber auch wichtige Punkt für eine funktionale Anforderung ist der Umgang mit Fehlern. Zu keinem dieser Zeitpunkte weiß ich genau, ob warenkorbbestellen einen Fehler mit sich gebracht hat. Es muss also für mich intuitiv sein, dass ich für den gesamten Transaktionsvorgang, mit Hilfe von try und catch, zentral den Fehler abwickeln kann. Wenn ich den Fehler stattdessen, wie üblich bei asynchronem JavaScript, in jeder dieser Funktionen einzeln bearbeiten muss, muss ich mir zusätzlich äußere Konstrukte bauen, um die gesamte Transaktion rückgängig zu machen. Eine ideale Lösung für asynchrone Probleme kann dies automatisch. Für unsere funktionalen Anforderungen ergibt sich also daher, dass wir die Anzahl der Aufrufe unserer Callback Funktionen limitieren möchten. Idealerweise nur einmal, denn genau das möchten wir garantiert bekommen. Genauso muss der Zeitpunkt des Aufrufs unseren Erwartungen entsprechen. Außerdem sollte die aufgerufene Lösung nicht die Rahmenbedingungen unserer eigentlichen Funktion ändern. Also beispielsweise den this Kontext neu vergeben. Und es sollte, zu guter Letzt, möglich sein, mit Ausnahmesituationen über alle asynchronen Funktionen hinweg umgehen zu können All die nun hier genannten Kriterien, sind im Übrigen auf Basis des Konstruktes von Promises, tatsächlich so auch umsetzbar.

JavaScript: Asynchrone Programmierung

Lernen Sie Lösungen für die komplexe Anwendungsentwicklung kennen, um zeitaufwändige Ressourcenzugriife im Code zu vermeiden.

2 Std. 30 min (19 Videos)
Derzeit sind keine Feedbacks vorhanden...
Software:
Exklusiv für Abo-Kunden
Erscheinungsdatum:22.08.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!