© istockphoto.com/yewkeo
Asynchrone Programmierung mit Observable Streams

Stream unter Kontrolle


Standards über Standards – und zahlreiche Bibliotheken, die versuchen, die Schnittstellen zu vereinheitlichen. Auf den folgenden Seiten erfahren Sie, was RxJS in diesem Umfeld für Sie leisten kann, und warum es sich auf jeden Fall lohnt, einen Blick darauf zu werfen.

Mit den technischen Möglichkeiten von JavaScript halten zahlreiche neue Programmierparadigmen Einzug in unseren Webentwickleralltag. Plötzlich müssen Sie sich nicht nur mit Callback-Funktionen und Events, sondern auch mit Promises und Datenströmen auseinandersetzen; der asynchrone Charakter vieler JavaScript-Applikationen kommt erschwerend hinzu. In diesem Umfeld sollen Sie jetzt umfangreiche und hochperformante Applikationen implementieren.

Glücklicherweise gibt es für sehr viele Problemstellungen bereits Bibliotheken, die Ihnen Arbeit abnehmen. Allerdings setzt nahezu jede dieser Bibliotheken auf andere Standards und bietet unterschiedliche Schnittstellen zur Anbindung an, was eine Integration in eine Applikation sehr umständlich macht. Aus dieser Not heraus entstehen immer wieder Bibliotheken, die dazu dienen, solche Schnittstellen zu vereinheitlichen. Einer der populärsten Vertreter dieser Art ist aktuell RxJS.

RxJS

RxJS geht aus dem Reactive-Extensions-Projekt hervor, das im Rahmen der Microsoft Open Technologies entstanden ist und eigentlich für die .NET-Plattform konzipiert wurde. Dieses Projekt erfreute sich solch großer Beliebtheit, dass es in weitere Programmiersprachen wie C++, Ruby, Python oder eben JavaScript portiert wurde. RxJS wird auf GitHub weiterentwickelt und ist ein Open-Source-Projekt unter der Apache License. Sie können RxJS sowohl in allen gängigen Browsern als auch serverseitig mit Node.js einsetzen; für beide Fälle werden Sie im Folgenden noch konkrete Beispiele sehen. Doch bevor Sie damit beginnen, sich den Quellcode herunterzuladen und Ihre ersten Schritte mit RxJS zu gehen, sollten Sie sich noch kurz Zeit nehmen, etwas mehr über die Hintergründe und Zusammenhänge dieser Library zu erfahren.

Zunächst soll es einmal um die Frage gehen, was denn genau RxJS ist und welchen Zweck es in einer Applikation erfüllen kann. Eine kurze, aber recht treffende Beschreibung lautet: RxJS ist wie lodash für Events – lodash ist eine Hilfsbibliothek, die viele Methoden zum Umgang mit Arrays und Funktionen mit sich bringt. Ein ähnlicher Werkzeugkasten ist auch RxJS, allerdings ist RxJS nicht nur auf Events beschränkt, sondern kann auch mit Arrays oder Promises arbeiten.

Damit Sie sich besser vorstellen können, was genau Sie mit RxJS anstellen können, folgt ein kleines Beispiel – als JavaScript-Entwickler sollten die verschiedenen Arraymethoden nichts Neues für Sie sein. Gehen Sie zunächst einmal von einem einfachen Array mit den Zahlen eins bis zehn aus. Für das Beispiel sind Sie nur an Zahlen interessiert, die größer als zwei und kleiner als sieben sind. Zu jeder Zahl soll außerdem der Wert fünf addiert werden; das Ergebnis soll dann ein aufsteigend sortiertes Array sein.

Natürlich gibt es für die Lösung dieser Aufgabe mehrere Ansätze. Sie könnten das Array selbstverständlich mit einer Schleife durchlaufen, jeden Wert prüfen und die entsprechenden Operationen ausführen. Wesentlich eleganter wird das Ganze natürlich, wenn Sie die Arraymethoden von JavaScript verwenden. Alle Zahlen zwischen 2 und 7 erhalten Sie beispielsweise, indem Sie das Array filtern. Die Addition bewerkstelligen Sie mit einem Aufruf der map-Methode, und die Sortierung übernimmt sort für Sie. Unter der Verwendung von Fluent Interfaces und Arrow Functions entsteht ein recht kompakter Codeblock, der Ihnen das korrekte Ergebnis liefert:

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let result = arr.filter(n => n > 2 && n < 7) .map(n => n + 5) .sort();

So weit, so gut. Jetzt stellen Sie sich aber eine ähnliche Aufgabe für einen Eventstream vor: Sie haben eine Folge von click-Events auf ein Element und sind nur an den Events interessiert, deren x-Koordinate größer als zehn und kleiner als 100 ist. Den x-Wert müssen Sie zur weiteren Verarbeitung schließlich um fünf erhöhen. Wäre es jetzt nicht schön, wenn Sie einen ähnlich kompakten Codeblock wie zuvor bei der Arrayverarbeitung auch für Events schreiben könnten? Das Problem hierbei ist nur, dass Events im Gegensatz zu einem Array keine Folge von Objekten sind, die zum Verarbeitungszeitpunkt schon vorliegen. Vielmehr sind sie asynchron, also erst zeitlich versetzt verfügbar. Was störend hinzukommt, ist die Tatsache, dass JavaScript außer über die Registrierung von Callback-Funktionen über keinerlei weiterer Routinen zur Verarbeitung von Events verfügt. Und genau hier kommt RxJS ins Spiel, wie das folgende Listing zeigt, das Events verarbeitet:

let source = Rx.Observable.fromEvent($('#mydiv'), 'click'); source.map(e => e.offsetX) .filter(offsetX => offsetX > 10 && offsetX < 100) .map(filtered => filtered + 5) .subscribe(mapped => console.log(mapped));

Machen Sie sich keine Sorgen, wenn Sie jetzt noch nicht jedes Detail dieses Listings verstehen, Sie lernen jede der beteiligten Komponenten im Folgenden noch genauer kennen.

Zunächst müssen Sie ein Observable für die click-Events generieren. Dieser Schritt stellt den Einstieg in die Eventverarbeitung dar. Mit dem daraus resultierenden Objekt können Sie dann weiterverfahren und beispielsweise die x-Koordinate des click-Events extrahieren. Anschließend filtern Sie alle Events heraus, die nicht den Anforderungen entsprechen – auf das Resultat haben Sie über die subscribe-Methode Zugriff. Die beiden Codeblöcke zur Arrayverarbeitung und zur Eventbehandlung ähneln sich größtenteils.

Anwendungsgebiete

Nachdem Sie RxJS nahezu überall einsetzen und mit mehr oder weniger Aufwand alle Datenstrukturen in RxJS verwenden können, sind die Einsatzgebiete kaum beschränkt. Normalerweise werden Sie RxJS überall dort einsetzen, wo Sie mit Asynchronität umgehen müssen; also beispielsweise bei Ajax-Requests an einen Server oder bei der Eventbehandlung. Wie Sie im vorangegangenen Beispiel gesehen haben, können Sie mit nur einem Funktionsaufruf jedes beliebige Browserevent mit RxJS behandeln. Ähnliche Routinen kommen auch serverseitig für Node.js zum Einsatz, wo Sie Dateisystemoperationen oder Netzwerkevents verarbeiten können.

Mit RxJS haben Sie die Möglichkeit, einen Workflow in Ihrer Applikation in kleine, sprechende Module zu unterteilen, was für eine bessere Lesbarkeit sorgt, den Testaufwand reduziert und die Erweiterbarkeit erhöht. Sie können in eine solche Methodenkette jederzeit zusätzliche Schritte einfügen oder bestehende Zwischenschritte entfernen, je nachdem, wie Ihre Anforderungen aussehen.

Wenn Sie sich mit RxJS beschäftigen, sind Sie in guter Gesellschaft: zahlreiche große und kleine Projekte setzen diese Bibliothek bereits ein. Eines der bekanntesten dürfte Angular 2 sein; hier kommt RxJS vor allem bei der Behandlung von Formularen und bei Anfragen zum Server zum Einsatz.

Installation

Die einfachste Variante, in den Genuss von RxJS kommen zu können, ist es, das Paket über npm zu installieren. Mit dem Kommando npm install rx wird das Paket heruntergeladen und in das lokale /node_modules/-Verzeichnis in Ihrem Projekt installiert. Natürlich können Sie auch andere Paketmanager wie beispielsweise Bower verwenden. Eine weitere Alternative ist, dass Sie sich den Quellcode direkt von GitHub herunterladen.

RxJS wird in verschiedenen Paket...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang