We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Reactive Programming

00:00

Formal Metadata

Title
Reactive Programming
Title of Series
Number of Parts
16
Author
License
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Reactive Programming mit JavaScript macht Spaß – und zwar nicht nur den Entwicklern, sondern auch den Benutzern einer Applikation. Das Ziel dieses Paradigmas ist eine Anwendung, die den Benutzer im Fokus hat, ihn kontinuierlich informiert hält und auch unter suboptimalen Bedingungen noch eine beeindruckende User Experience vermittelt. Die gute Nachricht hinter all dem: Sämtliche Technologien, die für ein reaktives System benötigt werden, stehen schon zur Verfügung. JavaScript-Entwickler müssen noch nicht einmal etwas Neues lernen, sondern lediglich ihre Vorgehensweise bei der Umsetzung etwas anpassen und ein paar Regeln folgen.
Computer programmingWindows Workflow FoundationJavaScriptComputer programmingComputer animation
Computer programmingComputer programmingSystems <München>Computer animation
Focus (optics)Computer programmingWEBSystems <München>
Computer programmingAktion <Informatik>Component-based software engineeringJavaScriptKommunikationSystems <München>Computer programmingReaktives SystemEvent horizonJavaScriptModule (mathematics)Web pageProgram flowchart
Structural loadModule (mathematics)Kopplung <Physik>Structural loadFault-tolerant system
Computer programmingWorld Wide WebSystems <München>Time zoneComputer programmingMathematicsComputing platformFacebookSimilarity (geometry)Computer animation
Computer programmingBindung <Stochastik>Data modelDataflowQuery languageLinieDirection (geometry)Event horizonFile viewerCode
Computer programmingWorld Wide WebGrand Unified TheoryComputer programmingArmComputer animation
Computer programmingNumberComputer programmingObject-oriented programmingSound effect
Windows Workflow FoundationoutputFiltrationComputer programmingWeb browserTape driveLengthEvent horizonCodeObject-oriented programmingData structureFünfzigComputer programmingASIA <Programm>Military operationComputer animation
MITISComputer programmingOpen sourceMicrosoftData streamEvent horizonJavaScriptMicrosoftArmImplementationComponent-based software engineeringOperator (mathematics)Curve fittingFRAMEWORK <Programm>Computer animation
Computer programmingWindows Workflow FoundationOperator (mathematics)Computer programmingFunctional programmingEncapsulation (object-oriented programming)Sound effectComputer animation
Computer programmingFunctional programmingPHPJavaScriptImplementationImplementationProgramming languageJavaScriptComputer animation
Web browserComputer programmingFunktionalitätNoten <Programm>FunktionalitätServer (computing)Web browserVersion <Informatik>Grand Unified TheoryComputer fileAtomic nucleusScripting languageScripting languageComputer animation
User interfaceComputer programmingServer (computing)Data structureEvent horizonTape drive
ProgrammablaufCollisionBALL <Programm>CodeInformationComputer animation
Computer programmingMilitary rankPerturbation theoryEvent horizon
Source codeComputer programmingData streamJavaScriptEvent horizonOperator (mathematics)Similarity (geometry)MittelungsverfahrenServer (computing)Abtrieb <Aerodynamik>Web browserMover <Programm>MassComputer animation
Computer programmingWindows Workflow FoundationSource codeCountingPattern languageTupleWorld Wide WebOperatorEvent horizonOperatorOperator (mathematics)Data streamPositionTape driveTupleLevel (video gaming)RoundingException handlingCodeComponent-based software engineeringInformationElectric currentData typeDiagramMaxima and minimaTouchscreenMover <Programm>Aktion <Informatik>Version <Informatik>Military rankDataflowService (economics)Military operationTOUR <Programm>CoroutineOmega <Programm>JavaScriptEvent-driven programmingDigital filterTime zoneNumberTiefeNormal (geometry)Value-added networkObject-oriented programmingQuery languageSeries (mathematics)Scripting languageComputer animation
Computer programmingScheduling (computing)CountingQueue (abstract data type)Scheduling (computing)JavaScriptFunktionalitätQueue (abstract data type)Web browserField extensionTask (computing)Frame problemMittelungsverfahrenScripting languageLogic gateSet (mathematics)Computer animationScripting language
Computer programmingScheduling (computing)Source codeWindows Workflow FoundationOperatorData streamEvent horizonElectronic data processingMilitary operationInformationMilitary rankSet (mathematics)Video game consoleEigenvalues and eigenvectorsOpen setMusical ensembleComputer animation
Windows Workflow FoundationComputer programmingSource codeChain ruleError detection and correctionError messageCodeCoroutineTime zoneComputer animation
Computer programmingData streamTape driveCoroutineChain ruleCASHEError detection and correctionComputer animation
Computer programmingChain ruleCoroutineInstanz <Informatik>Tape driveComputer animation
Computer programmingWindows Workflow FoundationTape driveInstanz <Informatik>Eigenvalues and eigenvectorsArmComputer animation
Windows Workflow FoundationComputer programmingoutputLevel (video gaming)CountingChain ruleInstanz <Informatik>CloningSource codeCoroutineLevel (video gaming)Event horizonoutputDigital filterVortexComputer animation
Computer programmingWindows Workflow FoundationWorld Wide WebACCESS <Programm>UploadingWeb browserCodeOperatorOperator (mathematics)Computer animation
Computer programmingUser interfaceComputer programmingComputer animation
Transcript: German(auto-generated)
Hallo, da fühlt man sich gleich wie so ein Rockstar auf der Bühne hier. Ich sehe euch bloß nicht vor lauter Licht. So, ich erzähle euch heute etwas über Reactive Programming. Funktioniert schon mal gut, nicht?
Hallo, René hat mich ja gerade schon größtenteils vorgestellt. Ich spreche Deutsch, bin aus München und JavaScript-Entwickler. Und ich werde euch heute erzählen was über Reactive Programming. Ein bisschen was zum Hintergrund. Woher kommt das?
Wie gliedert sich das in das ganze System ein? Und wie kann man das konkret machen? Es gibt da mehrere Libraries. Wir werden uns heute Reactive Extensions anschauen. Wenn euch das nicht taugt, gibt es ähnliche andere Libraries, die ihr benutzen könnt. Ja, so viel dazu.
Reactive Programming ist ein Teil dieser ganzen Reactive-Familie. Und die Grundlage davon bilden die Reactive Systems. Das ist eine Art und Weise, wie man Systeme gestaltet, um dem Benutzer möglichst großen Nutzen zukommen zu lassen.
Und zwar ist es ja so, wir sind hoffentlich alle Web-Entwickler. Und wir müssen da mit ganz anderen Problemstellungen umgehen, als in anderen Bereichen der Entwicklung, zum Beispiel Kommandozeilen-Applikation. In der Web-Entwicklung müssen wir sehr, sehr flexibel sein. Was Releases angeht, was Änderungsfrequenz angeht.
Das heißt wir brauchen schon mal Systeme, die diese Entwicklungsart erlauben und uns dabei unterstützen. Dann habt ihr es gerade gesehen, die BBC skaliert. Wir wollen das natürlich auch, zwar nicht mit Millionen von Nutzern, aber im kleineren Bereich.
Und wir wollen flexibel auf Fehler reagieren. Das heißt, wenn unsere Applikation sollte sich irgendwann mal doch ein Fehler einschleichen, wollen wir nicht, dass unsere komplette Applikation zum Stehen kommt, sondern nur ein bestimmter Teil nicht mehr funktioniert. Möglichst halt so, dass das Komplettsystem erhalten bleibt. Im Zentrum steht der Nutzer.
Das ist derjenige, der im Endeffekt dafür verantwortlich ist, dass wir unser Geld kriegen. Das heißt, unsere komplette Entwicklung richtet sich nicht danach, die neuesten Technologien auszuprobieren oder irgendwas sonst zu machen, sondern wir müssen dem Nutzer Mehrwert schaffen. Und da eignen sich diese reaktiven Systeme hervorragend dazu.
Die Säulen von so einem reaktiven System sind diese vier Punkte und da gliedert sich dieses Reactive Programming hervorragend ein. Werdet ihr gleich sehen warum. Responsive heißt, wir müssen schnell antworten. Der Nutzer muss immer wissen, wo er steht.
Wir gehen jetzt von einer Applikation aus, die dynamisch ist. Das heißt, ihr habt nicht eine Webseite, die der Nutzer von oben nach unten durchliest, sondern der Nutzer interagiert. Der Nutzer interagiert, indem er Daten produziert oder Daten konsumiert und Auswertungen macht oder ähnliches. Das heißt, auf unserer Seite bewegt sich was. Das muss schnell gehen, es gibt keine Wartezeiten.
Wir müssen, wie schon gesagt, mit Fehlern umgehen. Modulare Systeme eignen sich da hervorragend. Wenn ein Modul kaputt ist, ist das zwar unschön, aber die komplette Applikation ist immer noch funktionsfähig. Wenn ein Monolith kaputt geht, dann habt ihr ein Problem. Message-driven. Als JavaScript-Entwickler seid ihr mit Asynchronität und Event-Handling vertraut.
Das ist auch eins der Kernelemente von so einem reaktiven System. Und da eignet sich JavaScript hervorragend dafür, weil die ganzen Events schon im System drin sind und ihr eigentlich nur noch damit umgehen müsst.
Zu guter Letzt müssen wir elastisch sein, was die Last angeht, die auf unserem System wirkt, als auch die Features und alles drum herum. Das heißt, unser System muss dehnbar sein und muss auch Änderungen verkraften können.
Zusammengefasst müssen wir interaktiv sein. Das heißt, unser Nutzer muss mit uns arbeiten können, flexibel. Das heißt, wenn unser Nutzer jetzt statt blau-grün möchte, müssen wir das irgendwie einbauen können. Neue Features müssen sich integrieren lassen. Fehlertoleranz und Entkopplung gehen Hand in Hand.
Das heißt, wir brauchen ein Modulkonzept, mit dem wir arbeiten können. Und das Ganze muss skalierbar sein. So ein reaktives System ist nicht nur im Frontend, sondern auch im Backend, und das muss sich halt durchziehen. Das bringt nichts, wenn wir das beste Frontend haben, wenn unser Backend nicht mitspielt. Also wirklich einen durchgängigen Ansatz wählen.
So, reaktive Systeme haben wir jetzt genügend durchgekaut. Ich hoffe, ihr habt so einen groben Eindruck, um was es geht. Jetzt schauen wir uns an, was dieses Reactive Programming für uns tun kann. Wir fangen mit Grundschul Mathematik an. Eins und eins ist zwei. So, reaktive Programmierung heißt jetzt, wenn ich C ändere,
sollte sich auch A ändern, weil A eine Komposition aus B und C ist. Das heißt, eine Änderung in eurer Applikation kaskadiert komplett durch. Und das ist so das Grundkonzept von so einer reaktiven Applikation.
Nehmt euch Facebook oder eine andere Social Media Plattform. Wenn ihr irgendwo hinklickt, dann flackern plötzlich irgendwo Notifications auf oder Ähnliches. Und das will man eigentlich in der Applikation haben. Den Nutzer unterrichtet halten, den Nutzer informiert halten. Und ja, das funktioniert eben mit solchen Systemen.
Two-Way-Data-Binding sollte euch ein Begriff sein. Das beschäftigt sich damit, dass eine Änderung eben kaskadieren kann. Ihr kennt das wahrscheinlich aus Angular. Wer von euch damit schon zu tun hatte. Ihr habt ein Model und eine View. Die View kann das Model ändern.
Das Model kann die View ändern. Und jede Repräsentation eures Models wird abgedatet. Das hat nur ein kleines Problem. Wenn ihr mehr als 2000 solche Model-Repräsentationen auf eurer Seite habt, wird es mit Angular 1 relativ langsam. Das ist schlecht.
Der Code dazu. Aus dem Grund kehrt man immer mehr von diesem Dirty-Checking ab. Und geht hin zu unidirektionalem Datenfluss. Das heißt, die Daten fließen immer in eine Richtung. In React kennt man dieses System. Die Daten fließen von der Wurzel in die Blätter. Und das hat den riesen Vorteil, dass ihr nicht jeden Datenpunkt abfragen müsst,
ob der an der Änderung interessiert ist, sondern das kaskadiert durch und übernimmt für euch die Arbeit. Das Ganze läuft sehr viel über Events. Das heißt, die Events begegnen euch immer wieder.
Jetzt wenn ihr Reactive Programming machen wollt, müsst ihr etwas umdenken. Das heißt, diese alten Patterns mit linearen Programmfluss, die funktionieren leider nicht mehr. Ihr müsst sehr viel mit Callbacks arbeiten und einfach etwas anders an das Ganze rangehen.
Das Gute ist, das Handwerkszeug kennt ihr schon. Das habt ihr alle schon benutzt. Und ihr müsst nur noch etwas lernen, da reinzukommen. Das Ganze lässt sich sehr gut mit einem kleinen Array-Beispiel verdeutlichen. Arrays sagt euch was hoffentlich. Wer kennt sich nicht mit Arrays aus?
Sehr gut. So, kleine Programmieraufgabe für euch. Uns wird wahrscheinlich die Zeit nicht ausreichen, aber wir wollen nur gerade Zahlen und wir möchten, dass die Zahlen aufsteigend sortiert sind. Und ganz wichtig, immutable data structures.
Gewöhnt euch das an, dass ihr nicht Objekte editiert und Seiteneffekte erzeugt, weil das kann sehr hässlich in der Applikation werden, sondern versucht immer immutable data structures. Das heißt, ihr arbeitet auf diesem Array und jede Operation auf diesem Array erzeugt ein neues Array. Ist wesentlich weniger fehleranfällig,
ist wesentlich einfacher zu handhaben und auch wesentlich besser testbar. So, das ist JavaScript-Code und der macht das, was wir gerade wollten. Ihr habt die Eingabe dieses Arrays, das wird gefiltert und sortiert und das war's. Und wir erzeugen als Ausgabe, also Output,
ist ein neues Array. Wir haben jetzt alles erfüllt, was wir uns eigentlich zur Aufgabe gestellt haben. Wenn wir jetzt eins weitergehen, können wir Events im weitesten Sinne auch als solche Array-Elemente betrachten. Das heißt, ein Event-Stream ist nichts anderes als ein Array von Event-Objekten.
Und wenn ihr euch jetzt so einen Stream von Events mal anschaut und das als einzelne Datenelemente seht, also ihr habt hier das erste Element mit x 125, y 28, dann könnt ihr mit diesen Informationen arbeiten. Das heißt, uns interessiert in dem Fall nur
Events mit einem x-Wert von über 250. Sprich, in unserem Array-Beispiel hätten wir da einfach einen Filter angewendet. Was hindert uns dran, das hier auch zu tun? Wir haben Asynchronität, wir haben Events, aber mit Reactive Programming können wir Events auch als solche Datenobjekte betrachten
und Operationen damit machen. Das heißt, dieses ganze asynchrone Programmhandling wird für uns viel, viel einfacher, weil wir die Methoden, die wir eh schon auf Datenstrukturen anwenden, jetzt auch auf asynchronen Operationen anwenden.
Also Handwerkszeug, Asynchronität, Events und Datenströme. Kennt ihr alles schon. Dazu kommt noch eine Library, die heißt ReactiveX, Reactive Extensions. Das Ding ist von Microsoft entwickelt
und ist ein Framework, das euch ein paar Bauteile gibt, um euch die Arbeit mit solchen Event-Streams viel mehr zu erleichtern. Wir werden uns jetzt anschauen, wie diese ReactiveX-Implementierung in JavaScript aussieht. Und das Ganze besteht eigentlich
im Groben aus drei Teilen. Ihr habt Observables, ihr habt Operators und ihr habt Scandulas. Das sind die Kernkomponenten von Reactive Extensions. Und diejenigen unter euch, die fit mit Design-Patterns sind, wenn hier gleich mal das Observer-Pattern rausschmecken, ist nichts anderes.
Das Ganze gewürzt mit funktionaler Programmierung, weil es gerade so hip ist. Und ihr habt Reactive Programming mit Reactive Extensions. Das Ganze hat nichts mehr zu tun, als ihr kapselt alles schön in Funktionsblöcke, vermeidet Zeiteneffekte und eure Applikation wird wesentlich wartbarer.
So, jetzt haben wir dieses RxJS. Das ist die Adaption von Reactive Extensions auf JavaScript. Das ist eine Bibliothek, die könnt ihr euch runterladen, die ist open source. Es gibt von diesen Reactive Extensions für andere Programmiersprachen auch Adaptionen, wie zum Beispiel für C++, Python, Swift, PHP,
so eine Latte an Implementierungen. Das heißt, wenn euch JavaScript irgendwann zu langweilig wird, könnt ihr das Gelernte trotzdem auch in anderen Sprachen verwenden. Mehr braucht ihr nicht tun. Einfach die Datei laden. Dieses RxJS kommt in verschiedenen Variationen.
RxAll beinhaltet den kompletten Stack, da ist alles drin vom Funktionsumfang. Es gibt eine lite Version, da ist weniger drin. In der Dokumentation steht bei jeder Funktionalität, in welchem Paket dieses Ding enthalten ist. Das heißt, da müsst ihr etwas nachschauen, wenn ihr die Größe eures Scripts reduzieren wollt, ob ihr das All überhaupt
wirklich braucht. Das Gute ist, diese Reactive Extensions funktionieren nicht nur im Browser, sondern auch serverseitig mit Node. Beziehungsweise, wenn ihr kein NodeJS habt, sondern PAP oder ähnliches, könnt ihr auch auf Serverseite diese Reactive Extensions nutzen. Dieses RxNode
fügt einfach nur noch zusätzliche Funktionalitäten hinzu. Das heißt, im Kern ist dieses RxJS auch hier vorhanden und ihr könnt es einfach nutzen. Gut, Grundstruktur ist klar, dann kommen wir zu den Einzelheiten. Wir haben nämlich einmal die Observables.
Observables sind Datenpunkte, auf die sich Observer subscriben können. Und diese Observables emitten Events, das heißt, die benachrichtigen ihre Observer. Vom Workflow her ganz einfach, ihr definiert einen Observer, der mit den Events umgeht,
mit diesem Datenstream umgeht. Ihr definiert ein Observable auf einem Event, auf einer Datenstruktur, auf beliebigem. Dann verknüpft ihr die zusammen und dann seid ihr raus, weil dann übernimmt das System für euch und arbeitet selbstständig.
Code-mäßig sieht das relativ einfach aus. Ihr habt diesen Observer. Der Observer hat drei Möglichkeiten. Entweder er reagiert auf das nächste Event, es passiert einen Fehler, der behandelt wird, oder das Ding ist fertig, dann gibt es wieder eine Callback-Funktion. Das zweite ist ein Observable. Hier dieser RX-Observable-Range.
Das generiert euch einfach einen Array mit Informationen, die ihr konsumieren könnt. Und der dritte Punkt hier, dieses Source-Subscribe-Observer, verbindet diese beiden miteinander. Das heißt, ab diesem Punkt konsumiert euer Observer die Information aus dem Observable und ihr seid raus.
Dann gibt es zwei Varianten von Observables. Einmal gibt es diejenigen, die immer feuern. Das heißt, wenn ihr ein Observable auf Keyboard-Events baut und euer Benutzer drückt auf der Tastatur rum, dann werden die Events gefeuert, ob da ein Observer drauf ist oder nicht. Wenn ihr
diesen Range-Observable baut, dann muss sich zum Beispiel ein Observer drauf subscriben, bevor Daten konsumiert werden. Ist der Unterschied zwischen Hot und Cold? Bei den Hot-Observables kann es sein, dass euch Events durch die Lappen gehen, wenn ihr euch zu spät subscribt. Sollt ihr einfach nur wissen.
Ihr könnt euch auf alles Mögliche subscriben. Hier zum Beispiel auf Button-Clicks, auf Keyboard-Events, auf Mouse-Move-Events, auf irgendwas. Hauptsache, es produziert Events und da subscribt ihr euch drauf. Dafür gibt es von RX eine Methode, die heißt From Event. Und da werft ihr einfach
irgendwas rein, das Events generiert. In unserem Fall hier browserseitiges JavaScript. Funktioniert für Node.js ähnlich. Und dann kann es losgehen. Auch hier wieder Observer generieren, Observable generieren und beides verknüpfen. Und das war's schon. Jetzt ist das nur so mittelinteressant, weil ihr habt eine
Event-Quelle, ein Event-Ziel und die beiden hängen zusammen. Ist jetzt nichts Neues. Dazu kommen jetzt die Operators und hier wird's spannend. Weil ihr könnt zwischen Quelle und Ziel einfach Elemente einhängen, die irgendwas mit diesem Datenstrom tun. Und das ist genau die Stärke von diesen Reactive
Extensions, dass ihr nämlich genau diesen Datenstrom manipulieren und für euch arbeiten lassen könnt. Operators hängen an Observables und können verkettet werden. Das heißt, ihr führt einfach diesen Datenstrom weiter und könnt dann was damit tun. Ihr erinnert euch an das Arraybeispiel.
Filter, Sword, das sind unsere Operatoren. Diese Reactive Extensions haben eine sehr nette Art und Weise euch das Zeug beizubringen. Nämlich mit diesen Marble Diagrams. Es gibt für jeden Operator so ein Diagramm und der zeigt euch genau an, was diese Operation tut.
In unserem Fall haben wir hier die Map-Operation und die nimmt Kugeln, mappt das Ganze auf irgendwelche anderen Zeichen. Das heißt, es transformiert die Eingabe. So, die erste Kategorie von Observer, von Operators generiert euch
Observables. Die einfachste Form ist dieses ObservableCreate und da generiert er einfach einen ganz stumpfen Datenpunkt, der mit onNext Information rauswirft und onCompleted ist es beendet. Da könnt ihr Timeouts reinsetzen, da könnt ihr Intervalle reinsetzen. Das ist eigentlich euch
überlassen, was ihr hier macht. Da habt ihr die völlige Freiheit, müsst halt auch selber entwickeln. Das zweite ist dieser statische Observable. Das generiert euch einfach eine Range von Zahlen, von 0, 10 Elemente weiter. Das heißt, ein Array von 0 bis 10. Und dann habt ihr
noch die andere Möglichkeit auf Events zu subscriben. Ihr seht, das funktioniert asynchron und synchron und wird gleich behandelt. Das heißt, ob ihr jetzt eine synchrone Operation habt oder eine asynchron Operation, ist dem System eigentlich egal. Ihr subscribt euch da drauf und der Datenfluss wird immer gleich behandelt, ob das jetzt synchron oder asynchron ist.
Dann habt ihr diese Transform Operators. Wenn ihr so einen Datenstrom aufgesetzt habt, werft ihr da zum Beispiel so ein Map drauf und transformiert die eingehenden Werte in ausgehende Werte. Wenn ihr euch vorstellt, ihr habt so ein Click Event und seid nur an der Position dieses Click Events interessiert,
werft ihr die eingehenden Events in so einen Datenstrom rein, zieht euch nur die Position raus und gebt die dann weiter. Also ihr modifiziert das Ganze. Da gibt es noch zig andere Transform Methoden, wie zum Beispiel Group By. Ihr könnt ähnliche Elemente, wie hier zum Beispiel
die Runden zusammengruppieren, könnt zählen, wie viele Runde Events habe ich, wie viele eckige Events habe ich. Da gibt es noch eine ganze weitere Palette. Dann habt ihr die Möglichkeit, diesen Datenstrom einzuschränken. Euch interessiert nicht jedes Event, sondern zum Beispiel nur
Click Events, die in einem bestimmten Screen Bereich auftreten, oder Information mit einem bestimmten Wert von bis. Da könnt ihr diese Filteroperation reinpacken, da könnt ihr zum Beispiel mit Distinkt filtern, dass ihr nur eindeutige Ergebnisse kriegt und nicht Wiederholungen davon, um die Information eben einzuschränken
und dann gezielter weiterarbeiten zu können. Gerade bei Events ist es so, wenn ihr Mouse Move Events habt und die innerhalb von einer bestimmten Toleranzgrenze sich nur ändern, dann interessiert euch das nicht. Da könnt ihr zum Beispiel rausfiltern. Ihr könnt auch Observables
kombinieren und da habt ihr auch verschiedene Möglichkeiten. And, then, do and when kombinieren mehrere Observables zu einem Tupel. Das heißt, ihr habt hier zwei Event Streams oder zwei Observable Streams
und die wollt ihr zu einem kombinieren. Dann nehmt ihr erstmal eure Observables, verknüpft die anhand eines Patterns mit diesen Unverknüpfungen, dann entwickelt ihr einen Plan daraus mit diesem then do und einer Callback Funktion, um zu bestimmen, wie diese resultierenden Tupels aussehen sollen
und schließlich könnt ihr euch mit diesem Observable when an diesen Datenstrom knüpfen und dann Aktionen ausfüllen. Der Code hier führt dazu, dass jeder Wert dieses Streams in einem Tupel eingebunden wird.
Das hat den Nachteil, wenn ihr asynchrones Streams verbindet, dass die Generation des nächsten Tupels auf den langsamsten Stream wartet. Das kann unter Umständen schlechte Performance nach sich ziehen. Also da müsst ihr auch immer aufpassen, was hat das für Auswirkungen, was sie tut. Da müsst ihr sehr wohl auf eure Asynchronität achten.
Dann habt ihr die Möglichkeit, solche Datenströme auch zu merchen. Das heißt, es kommen Events aus mehreren Strömen und ihr wollt das zu einem zusammenfassen, weil ihr da einen gemeinsamen Dispatcher oder ähnliches habt. Ihr könnt euch das vorstellen, wie zum Beispiel
Klicks auf verschiedene Buttons oder Elemente oder verschiedene Eingaben. Die zieht ihr in einen Stream zusammen, mercht die zusammen und könnt dann eine gemeinsame Behandlungsroutine auf das Ganze anwenden. Hier hängt es auch immer davon ab, wann wird so ein Event emitted. Das heißt, ihr habt da relativ
wenig Kontrolle drüber, wie die Reihenfolge ist, sondern das wird einfach in euren Stream reingepustet und ihr geht dann so damit um, wie ihr es braucht. Dann könnt ihr so Dinge machen, wie ist in meinem Stream ein bestimmtes Element
enthalten oder erfüllt mein Stream eine bestimmte Bedingung. In unserem Array-Fall habe ich hier zum Beispiel die Abfrage, ist jedes Array-Element numerisch? Wenn nicht, kann ich eine Ausnahmebehandlung machen, wenn ja, kann ich einfach weiter. Das ist so eine Art
Validation, um eure Datenströme zu prüfen und wenn die valide sind, einfach weiter zu machen. Dann könnt ihr prüfen, ist ein bestimmtes Element in meinem Datenstrom enthalten oder auch nicht. Dazu könnt ihr dann auch sagen, mein Datenstrom lebt nur eine bestimmte Zeit, dann beende ich diesen
Datenstrom und nach Beendigung könnt ihr dann die Prüfung stattfinden lassen. Auch wieder wichtig, dass ihr mit diesem asynchronen Charakter von dem System auch etwas spielt und umgehen könnt, weil es bringt euch nichts, wenn ihr da wunderbare Aktionen drauf macht und eben wissen wollt, ob jedes Element eures Streams eine bestimmte Kondition
erfüllt. Wenn der Stream nie endet, werdet ihr das nie rausfinden. Natürlich kannst du eine Frage stellen. Ja, ist eine gute Frage.
Sobald der das erste findet, hör da auf damit. Bei Every ist es so, er muss prüfen ob all, genau. Dann habt ihr was auch sehr schick ist,
mathematische Operatoren. Das heißt, ihr könnt Informationen über euren Stream entweder zusammenfassen, Extremwerte berechnen lassen. Das ist recht praktisch, wenn ihr irgendwelche Charting- Auswertungen habt, um da nicht selber coden zu müssen, sondern da wird euch ein ganzer Satz an Operatoren schon zur
Verfügung gestellt und mit denen könnt ihr umgehen. Wenn ihr den Fall haben solltet, dass ihr so einen Event-Stream habt und aus dem dann wieder einen ganz normalen JavaScript- Datentyp machen wollt, gibt es diese 2 Operatoren. Also ihr könnt aus einem Event-Stream
ein Array wieder machen. Oder ihr könnt aus so einem observable range auch wieder ein JavaScript-Array machen, um damit weiterzumachen. Das macht vor allem Sinn, wenn ihr an einem bestimmten Punkt seid und diese Reactive-Extensions in euren Legacy-Code integrieren wollt und da eine bestimmte Datenform aufweisen müsst,
um es weiterzubehandeln. Da machen diese 2 Operatoren sehr viel Sinn. Das ist nicht nur auf Array beschränkt, sondern auch auf ECMAScript 2015 Maps und Sets. Das heißt, ihr habt da wirkliche Datenmengen, die ihr dann einfach weiterreichen könnt.
So, jetzt ist es so, dass diese Vielfalt von Operatoren einen ziemlich schnell erschlagen kann. Und aus dem Grund gibt es so einen Decision Tree, und der hilft euch, den richtigen Operator für euren Zweck zu finden. Das heißt, ihr könnt hier sagen, ok, ich habe
ein bestimmtes observable und das möchte ich anhand eines bestimmten Kriteriums filtern, um eine Ausgabe zu erzeugen. Dann wird hier rauskommen, bitte nutzt den Filteroperator. Wenn ihr habt, ich möchte eine zeitverzögerte Abfolge von meinen Events haben,
dann nutzt bitte einen Delay- Operator. Und so könnt ihr euch da durchrangeln, weil es ist wirklich so eine riesen Liste von Operatoren, die euch da zur Verfügung steht. Und da findet man sich nicht so schnell zurecht. Und es ist meistens so, dass ihr von einer Problemstellung ausgeht und dann das Werkzeug sucht
und nicht das Werkzeug kennt und euer Problem sucht. So soll es zumindest in der Realität sein. Und aus dem Grund ist das eine sehr gute Hilfe. Findet sich in der Dokumentation wieder. Da gibt es auch eine interaktive Version davon. Das heißt, ihr könnt euch da durchklicken und euch wird weiter geholfen.
Neben den observables und den Operators gibt es dann noch eine dritte Komponente. Das sind die scheduler. Und so ein scheduler bestimmt den Ausführungskontext eines observables. Das ist in JavaScript jetzt so mittelsinnvoll.
Das macht vor allem Sinn in anderen Sprachen. Da könnt ihr Threadpools nutzen und andere Dinge. In JavaScript ist die Funktionalität etwas reduzierter, etwas weniger komplex. Für uns gut. Da gibt es verschiedene scheduler. Der Standard,
oder wenn ihr null übergebt, wird synchron ausgeführt. Also einfach ihr subscribt euch, dann passieren irgendwelche Dinge und dann läuft eure Applikation weiter. Es gibt die Möglichkeit das Ganze in eine Warteschlange zu stecken. Wenn die abgearbeitet ist, wird dann die nächste Operation abgearbeitet.
Und so weiter. Dann dieses ASAP, schnellstmögliche Verarbeitung. Also eure Tasks werden zum nächsten möglichen Zeitpunkt ausgeführt, wenn euer Browser wieder Ressourcen frei hat. Async, entkoppelt das Ganze. Asynchrone Verarbeitung erreicht ihr am besten
mit einem SetTimeout von null. Dann seid ihr aus dem ausführenden Kontext raus, eure Operation laufen weiter und das Ganze ist entkoppelt. Und dann gibt es noch eine nette Erweiterung. Die heißt ARIXJS DOM. Und da könnt ihr auch auf die Animation Frames eures Browsers gehen und die Animation
im Browser flüssiger gestalten. Das ist sehr gut, wenn ihr Animations- oder grafiklastige Applikation entwickelt, um die Animation flüssig zu gestalten. Dieses 60 frames per seconds Ziel lässt sich hiermit sehr gut erreichen und ihr habt einen Scheduler, der dafür sorgt, dass eure Operation immer in diesen Timeframes
passieren und eure Applikation einfach gut und flüssig aussieht. Wie so ein Scheduler wirkt, können wir uns am besten an einem Beispiel anschauen. Und zwar haben wir hier einen Range Operator. Der generiert uns ein Observable.
Wir subscriben uns drauf und geben einfach nur die Elemente aus. Standard-File, Console-Log, before-subscribe, dann werden unsere Operation abgearbeitet, dann after-subscribe. Ganz normaler, synchroner Programmfluss. Diese Operationen blockieren, das heißt, wenn ihr da viel macht,
wird erstmal blockiert. Wenn ihr das Ganze asynchron schedulet, dann habt ihr hier das before-subscribe, dann habt ihr eure Operationen und dann habt ihr das after-subscribe. Wird aber entkoppelt ausgeführt, das heißt, ihr habt erst das Console-Log
davor, dann habt ihr das Console-Log danach und dann kommen erst eure entkoppelten Operationen. Ihr braucht euch hier nur vorstellen, wenn ihr eine große Menge an Daten verarbeiten wollt, kann es durchaus sinnvoll sein, wenn ihr das entkoppelt, eure Applikation bleibt responsiv, der Nutzer kann trotzdem noch interagieren und
die Events werden dann abgearbeitet, wenn wieder Ressourcen zur Verfügung stehen. Wenn ihr jetzt solche Event-Händler baut für Click- und Tastatur-Events, die werden schon für euch asynchron abgehandelt.
Das heißt, ihr müsst euch da keine Sorgen machen, dass ein Button, ein Warten auf einen Button-Click, der irgendwann in der Zukunft passiert, eure Applikation zum Stehen bringt. Also das übernimmt das System schon für euch. Das ist vor allem wichtig, wenn ihr so synchrone Datenverarbeitung mit einem eigenen Observable dann starten wollt.
Damit haben wir jetzt die drei Kernpunkte von RXJS gesehen. Das heißt, ihr habt die Observables, die Informationen generieren. Ihr habt die Operators, die auf dem Datenstrom und den Informationen arbeiten. Ob das jetzt synchron generierte Informationen, wie so eine Range, oder asynchrone
Operationen, wie Klicks oder ähnliches sind, ist euch eigentlich egal. Und ihr habt den Observer, der am Ende steht, kombiniert das Ganze mit euren Schedulers, die dafür sorgen, dass das Ganze im richtigen Kontext und in der richtigen Art und Weise ausgeführt wird. Jetzt haben wir natürlich noch unsere
Anforderungen, dass wir mit Fehlern umgehen können. In so einem Datenstrom kann es immer passieren, dass ein Fehler auftritt. Ihr erinnert euch eventuell daran, dass wir am Anfang den Fall hatten, dass ihr so einen Observer create und da habt ihr das OnNext, das einfach den nächsten
Wert in diese Kette reinwirft. Und OnError löst einen Fehler aus. Das heißt, ihr habt eine Möglichkeit von Fehlerbehandlung, die in einem Exception-Handling gleich kommt. Wenn so ein Fehler auftritt, wird erstmal die Verarbeitung angehalten und eine Fehlerbehandlungsroutine ausgeführt. Das heißt,
ihr habt grundsätzlich die Möglichkeit von so einer Art Try-Catch im homosynchronen Kontext das Ganze auszuführen. Code-mäßig sieht es so aus. OnError wirft so einen Fehler und ihr habt beim Subscribe die Möglichkeit, eine Error- Behandlungsroutine
anzugeben. Die wird dann im Fehlerfall aufgerufen und behandelt euren Fehler. Try-Catch, euer Stream ist aber dann beendet. Also diese Fehlerbehandlungsroutine markiert das Ende eines solchen Datenstroms. Der ist dann tot. Der gesamte Datenstrom.
Also ihr lauft, wenn ihr euch diese Murmelkette vorstellt, in der Mitte passiert ein Fehler, ihr lauft bis zur dritten Murmel, dann passiert der Fehler und dann ist erstmal Schluss. Muss aber nicht sein. Ihr habt mehrere Möglichkeiten. Also das war jetzt die Standard-Routine. Es gibt die Möglichkeit
mit solchen Fehlern umzugehen und zwar mit einem Catch könnt ihr aus verschiedenen Observables den auswählen, der keinen Fehler wirft. Das ist relativ praktisch. Und ihr habt noch die Möglichkeit, zum Beispiel mit einem Retry das Ganze nochmal aufzurufen in der Hoffnung, dass der Fehler nicht wieder auftritt.
Also da gibt es auch die verschiedensten Varianten mit Fehlern in so einer Kette umzugehen. Ihr habt die Möglichkeit, so verschiedene Sequenzen miteinander zu mergen und wenn ein Fehler auftritt, den Fehler ans Ende dieser Sequenz zu setzen. Dass die Fehlerbehandlungsroutine erst greift, wenn alle anderen
nicht fehlschlagenden Sequenzen fehlerfrei durchgelaufen sind. Da sind wir dann auch schon bei der Kombination von mehreren Streams. Grundsätzlich könnt ihr das schon tun. Also ihr könnt mehrere Streams miteinander kombinieren. Das Problem ist, jeder Stream besitzt seine eigene Observable Instanz.
Das Problem dabei ist, wenn ihr zum Beispiel auf einen Fehler reagieren wollt, dann tritt er nicht zwingend in jeder Instanz des Observables auf. Das heißt, ihr wollt eigentlich immer auf derselben Instanz dieses Observables arbeiten, damit ihr
Fehler und ähnliche Ausnahmesituation immer mitkriegt. Aus diesem Grund gibt es diese Subjects. Und so ein Subject könnt ihr euch vorstellen wie so ein Verteiler in dem Strom. Ihr setzt den einfach zwischen rein und dann passiert Folgendes.
Ihr habt die eine Observable Instanz und die wird auf mehrere verteilt. Das ist quasi eine Weiche, die immer wieder Klone desselben Events erstellt und an alle Eingabe fällt. Das Problem ist, wenn ihr das nicht macht, es tritt irgendwo ein Fehler auf, dann kann es sein, dass in der einen Routine der Fehler auftritt, in der anderen
Routine der Fehler nicht auftritt und dann seid ihr leider raus. Jetzt haben wir noch ein kleines Beispiel, damit ihr auch seht, dass sich das in der Realität umsetzen lässt. Wir haben ein Eingabefeld und wir wollen zählen, wie viele Buchstaben in diesem Element
eingegeben wurden. Dazu nutzen wir erstmal ein Map und ein Deep Bounce. Wir kriegen Keyboard Events rein. Wir ziehen uns da nur den Wert raus, der eingegeben wurde. Wir wollen nicht bei jedem Keyboard Event das Ganze berechnen, weil das uns viel zu viel Arbeit ist.
Für uns ist es nur relevant, wenn es eine Sekunde Zeit verzögert ist, das heißt wir sammeln den ganzen Kram und geben es dann einmal gesammelt aus. Source Code sieht folgendermaßen aus. Ihr holt euch das Inputfeld, ihr holt euch das Ausgabefeld. Ihr legt einen Observable an für dieses
KeyUp Input Event. Ihr wendet dann den Map Filter an. Ihr wendet dann den Deep Bounce Filter an. Also wenn eine Sekunde lang kein weiteres Event passiert, dann wird die nächste Routine in der Kette ausgeführt und diese nächste Routine ist die Subscription und dann gebt ihr einfach
den Wert, den ihr da berechnet habt, in das Ausgabefeld ein. Und das war's. Das ist jetzt ein ganz triviales Beispiel und das findet ihr in jedem weiteren halbwegs vernünftigen Tutorial auch wieder, was ich viel spannender an der ganzen Sache finde.
In diesen Reactive Extensions, in dem GitHub Repo, gibt's eine Seite, die heißt Examples. Und, nein, und diese Examples beinhalten ganz viele Beispiele von real world
Szenarien, wo ihr diese Reactive Extensions anwenden könnt. Das reicht von ganz einfachen Dingen, wie ich euch gerade hier gezeigt hab, mit ich setz einfach Operators hintereinander bis hin zu kleinen Spielen, wo ihr dann hier schon seht,
der Code ist etwas umfangreicher, aber ihr findet halt hier wirkliche Anwendungsszenarien, wie ihr das Ganze in der richtigen Applikation handeln könnt. Ihr habt hier Observer-Begenerierung, ihr habt hier Subscriptions, ihr habt Operator-Anwendung,
also da könnt ihr auch gut und gerne mal drin stöbern, mal schauen, was euch da über den Weg läuft, was für euch Sinn macht, einfach mal Anregungen holen, einfach mal das Zeug runterladen, in eurem Browser selber ausprobieren, mal schauen, wenn ihr da an der einen oder anderen Stelle was dreht, wie verhält sich die Applikation,
das bringt mehr als Doku lesen, weil da kann man sich die Finger mal schmutzig machen und Dinge damit tun. Das ist mein Beispiel übrigens schamlos von hier geklaut, das ist diese Operator-Hintereinander-Reiung und ihr seht einfache Beispiele bis zu relativ
komplexen, mit D3.js zum Beispiel, also da könnt ihr euch ruhig auch mal Anregungen holen. Damit sind wir so weit durch. Ein kurzer Überblick über Reactive Programming mit RX.js.