Heim >Web-Frontend >js-Tutorial >10 Notwendigkeit, RXJS-Funktionen mit Beispielen zu wissen
Dieser Artikel wurde von Florian Rapppl und Moritz Kröger überprüft. Vielen Dank an alle Peer -Rezensenten bei SitePoint für die perfekte Erstellung von SitePoint -Inhalten!
Als Interesse an funktionaler reaktiver Programmierung (FRP) wächst RXJS zu einer der beliebtesten JavaScript -Bibliotheken in diesem Paradigma. In diesem Artikel werden wir die zehn wichtigsten Funktionen in RXJs untersuchen.
Hinweis: In diesem Artikel geht davon aus, dass Sie mit den Grundlagen von RXJs vertraut sind, wie im Artikel "Beginnend mit funktionaler reaktivem Programmieren mit RXJs" beschrieben.
map()
, filter()
, reduce()
und take()
, Spiegelarray -Operationen, werden jedoch auf Streams von Zahlen angewendet, die Werte im Laufe der Zeit emittieren. flatMap()
und switch()
sind entscheidend für die Behandlung komplexer Datenstrukturen und die separate Verwaltung mehrerer Streams, wodurch sie für fortschrittliche reaktive Programmieraufgaben von entscheidender Bedeutung sind. concat()
, merge()
und combineLatest()
können verwendet werden, um mehrere Streams effektiv zu kombinieren, von denen jede eine andere Rolle bei der Stream -Management und der Datensynchronisation spielt. takeUntil()
bietet einen Mechanismus, der auf externen Bedingungen basiert, die sich abmelden, was die Flexibilität von RXJs in der Flussregelung und des Ressourcenmanagements veranschaulicht. reaktive Programmierung ist ein Programmierparadigma, das den Datenstrom nennt, der als Basis -Programmiereinheit bezeichnet wird.
Stream - oder beobachtbare Objekte in Rxjs Jargon - Allike Event Hörer: Beide warten darauf, dass etwas passiert, und benachrichtigen Sie, wenn es passiert. Eine Reihe asynchroner Benachrichtigungen, die vom Onclick -Hörer erhalten wurden, sind ein perfektes Beispiel für den Datenfluss.
Mit anderen Worten, das beobachtbare Objekt ist nichts anderes als ein Array, das im Laufe der Zeit gefüllt ist.
Elemente dieses Arrays können von fast überall stammen: Dateisystem, DOM -Ereignisse, API -Aufrufe und sogar synchrone Daten wie Arrays. Grundsätzlich ist die reaktive Programmierung nichts anderes, als beobachtbare Objekte als Bausteine von Programmen zu verwenden.
Arrays sind einfach, da ihr Inhalt endgültig ist, es sei denn, es wird explizit geändert. In diesem Sinne gibt es in einem Array keine wesentliche Zeitlichkeit.
Andererseits werden beobachtbare Objekte nach der Zeit definiert. Höchstens wissen Sie, dass der Stream bisher erhalten hat [1, 2, 3]. Sie können nicht sicher sein, ob Sie 4 oder nicht - und es ist die Datenquelle, nicht Ihr Programm, das dies bestimmt.
Die Beziehung zwischen Streams und Arrays ist so tiefgreifend, dass die meisten reaktiven Erweiterungen aus der Welt der funktionalen Programmierung stammen, in der Listenvorgänge Kern sind.
Betrachten Sie gemeinsame Aufgaben-Apps. Lassen Sie uns die Frage sehen, wie der Name der unvollendeten Aufgabe eines Benutzers mit RXJS angezeigt wird:
<code class="language-javascript">const task_stream = // 创建所有数据库中任务的流 getTasks(). // 只获取此用户的任务 filter((task) => task.user_id == user_id). // 获取未完成的任务 filter((task) => !task.completed). // 只获取任务名称 map((task) => task.name) /* 任务如下所示: task = { user_id : number, completed : boolean, name : string } */</code>
bisher ist dies nur eine Array -Erweiterung, zeigt jedoch den funktionellen Stil der reaktiven Programmierung.
Die deklarative Natur wird deutlich, indem komplexere "reale Welt" -Funktionen hinzugefügt werden. Angenommen, wir wollen:
<code class="language-javascript">const task_stream = parameter_stream. debounce(1000). map((parameter) => { getTasks(). retry(3). filter((task) => task.user_id === user_id). filter((task) => task.completed === parameter). map((task) => task.name) }). flatMap(Rx.Observable.from). distinctUntilChanged(). update()</code>
parameter_stream sagt uns, ob der Benutzer abgeschlossene oder unvollendete Aufgaben will, und speichert die Auswahl im Parameter
dunounce () stellen Sie sicher, dass wir uns nur auf die letzte Schaltfläche pro Sekunde konzentrierenEinfache, direkte und leistungsstarke Fehlerbehandlung.
Beim Durchsuchen der Top Ten Must-Know-Funktionen von RXJs werden wir auf jeden der Funktionen in den obigen Beispielen begegnen.
filter ()
take () / take thing ()
Rückruf als Parameter;
Führen Sie es auf jedem Element des Arrays aus, das Sie aufrufen
Gibt ein Neues Array zurück, in dem jedes Element des ursprünglichen Arrays durch das Ergebnis ersetzt wird, das durch den Rückruf darauf erzeugt wird.
Es gibt ein neues beobachtbares Objekt zurück, kein Neues;
<code class="language-javascript">const task_stream = // 创建所有数据库中任务的流 getTasks(). // 只获取此用户的任务 filter((task) => task.user_id == user_id). // 获取未完成的任务 filter((task) => !task.completed). // 只获取任务名称 map((task) => task.name) /* 任务如下所示: task = { user_id : number, completed : boolean, name : string } */</code>
Hier verwenden wir MAP, um jedes Benutzerobjekt im eingehenden Stream durch die Website jedes Benutzers zu ersetzen.
Mitrxjs können Sie auch map () als select () aufrufen. Beide Namen beziehen sich auf dieselbe Funktion.
<code class="language-javascript">const task_stream = parameter_stream. debounce(1000). map((parameter) => { getTasks(). retry(3). filter((task) => task.user_id === user_id). filter((task) => task.completed === parameter). map((task) => task.name) }). flatMap(Rx.Observable.from). distinctUntilChanged(). update()</code>Dies wird nur Benutzer ausgewählt, deren Website in "net" oder "org" endet.
filter () hat auch einen Alias where ().
3.
record () ist häufig der verwirrendste grundlegende Listenbetrieb, da das Verhalten im Gegensatz zu Filter () oder MAP () je nach Verwendung variiert.
Normalerweise nimmt Reduzierung () eine Sammlung von Werten auf und konvertiert sie in einen einzelnen Datenpunkt. In unserem Beispiel geben wir ihm einen Website -Namens -Stream an und verwenden reduziert (), um diesen Stream in ein Objekt umzuwandeln, das die Summe der Anzahl der gefundenen Websites und deren Namenslänge berechnet.
hier vereinfachen wir den Stream zu einem einzelnen Objekt, das verfolgt:
<code class="language-javascript">source. map((user) => user.website)</code>
Wie viele Websites haben wir gesehen;
take () und take the Take () ergänzen die grundlegenden Funktionen einfacher Streams.
Wir können jedes Mal, wenn wir die Website erhalten, scan () zum Aussenden unseres Objekts und nur die ersten beiden Werte verwenden.
rxjs bietet auch TakeIth (), sodass Sie Werte erhalten können, bevor ein bestimmter boolescher Test festgelegt wird. Wir können Take the Take () verwenden, um den obigen Stream wie folgt zu schreiben:
<code class="language-javascript">source. map((user) => user.website). filter((website) => (website.endsWith('net') || website.endsWith('org')); })</code>Fließbetrieb mit hoher Ordnung
Diese Funktionen sind nahezu gleich wie bekannte Listenvorgänge, außer dass sie eher an beobachtbaren Objekten als an Arrays arbeiten.
<code class="language-javascript">source. map((user) => user.website). filter((website) => (website.endsWith('net') || website.endsWith('org'))). reduce((data, website) => { return { count : data.count += 1, name_length : data.name_length += website.length } }, { count : 0, name_length : 0 })</code>
So wie ein Array Daten enthalten kann, die komplexer sind als einfache Werte (z. B. ein Array oder Objekt), können beobachtbare Objekte auch Daten höherer Ordnung wie Versprechen oder andere beobachtbare Objekte aussagen. Hier kommen mehr professionelle Tools ins Spiel.
5.
… in der Tat verwenden wir es bereits!
Wenn wir den Quellstrom definieren, rufen wir Promise () und flatMap ():
auf
from Promise;
rx.observable.from;<code class="language-javascript">source. map((user) => user.website). filter((website) => (website.endsWith('net') || website.endsWith('org'))). scan((data, website) => { return { count : data.count += 1, name_length : data.name_length += website.length } }, { count : 0, name_length : 0 }). take(2);</code>Flatmap.
Versprechen ist, dass es nur einen zukünftigen Wert darstellt. Es kann nicht mehrere asynchrone Daten zurückgeben.
Dies bedeutet, dass wir, wenn wir rx.observable.frompromise () verwenden, ein beobachtbares Objekt erhalten, das einen einzelnen Wert ausgibt - oder:
6
Bei Verwendung von FlatMap ():
rufen Sie FlatMap () auf beobachtbare Objekte auf, die eine Einzelwertauflösung oder Ablehnung des Versprechens ausstellen;
Dies deckt den Code in unserem kurzen Vorwort ab:
<code class="language-javascript">const task_stream = // 创建所有数据库中任务的流 getTasks(). // 只获取此用户的任务 filter((task) => task.user_id == user_id). // 获取未完成的任务 filter((task) => !task.completed). // 只获取任务名称 map((task) => task.name) /* 任务如下所示: task = { user_id : number, completed : boolean, name : string } */</code>
rxjs bietet auch einen Alias für flatMap (): selectMany ().
<code class="language-javascript">const task_stream = parameter_stream. debounce(1000). map((parameter) => { getTasks(). retry(3). filter((task) => task.user_id === user_id). filter((task) => task.completed === parameter). map((task) => task.name) }). flatMap(Rx.Observable.from). distinctUntilChanged(). update()</code>kombiniert mehrere Streams
Normalerweise haben wir mehrere Streams, die kombiniert werden müssen. Es gibt viele Möglichkeiten, Streams zu kombinieren, aber einige erscheinen häufiger als andere.
Verbindung und Zusammenführung sind die beiden häufigsten Möglichkeiten, Ströme zu kombinieren.
Merge erstellt neue Streams aus mehreren Streams, indem der Wert eines aktiven Streams
emittiert wirdDenken Sie darüber nach, mit zwei Personen gleichzeitig auf Facebook Messenger zu sprechen. concat () ist eine Situation, in der Sie eine Nachricht von beiden Parteien erhalten, aber ein Gespräch mit einer Person abschließen, bevor Sie auf eine andere Person antworten. Merge () ist wie das Erstellen eines Gruppenchates und das Empfangen von zwei Nachrichtenströmen gleichzeitig.
Der Stream
concat () druckt zunächst alle Werte von Source1 aus und druckt nur den Wert von Source2, nachdem Source1 beendet ist.merge () Der Stream druckt die Werte von Source1 und Source2 gemäß der empfangenen Reihenfolge: Er wartet nicht, bis der erste Stream abgeschlossen ist, bevor der Wert des zweiten Streams abgibt.
<code class="language-javascript">source. map((user) => user.website)</code>
8
Normalerweise möchten wir auf beobachtbare Objekte zuhören, die beobachtbare Objekte abgeben, sich jedoch nur auf die neuesten Emissionen der Quelle konzentrieren.Um die Analogie von Facebook Messenger weiter zu erweitern, switch () sind Sie ... nun, die Person, die Sie antworten, basierend darauf, wer derzeit die Nachricht sendet.
Die Benutzeroberfläche bietet mehrere gute Anwendungsfälle für Switch (). Wenn unsere Anwendung jedes Mal eine Anfrage stellt, wenn der Benutzer wählt, wonach er suchen möchte, können wir davon ausgehen, dass er nur die Ergebnisse der neuesten Auswahl sehen möchte. Daher verwenden wir Switch (), um nur für die neuesten Auswahlergebnisse zuzuhören.
übrigens sollten wir sicherstellen, dass wir keine Bandbreite verschwenden und nur zum letzten Mal Zugriff auf den Server auswählen, wenn ein Benutzer jede Sekunde herstellt. Die Funktion, die wir dafür verwenden, heißt DEBOINCE ()
Wenn Sie in die andere Richtung gehen und nur der ersten Wahl folgen möchten, können Sie Drosselklappen () verwenden. Es hat die gleiche API, verhält sich aber das Gegenteil.
Zur Demonstration erstellen wir ein weiteres Dropdown-Menü und ermöglichen den Benutzern die Auswahl der ID des Elements, das sie abrufen möchten.
Es gibt zwei Situationen. Wenn Benutzer:
Die aktuelle Auswahl des Benutzers von Endpunkt;
Die kürzlich vom Benutzer ausgewählte ID.Wenn ein Stream einen Wert ausgibt, nimmt CombinEnelatest () den emittierten Wert und kombiniert ihn mit dem letzten von den anderen Streams emittierten Elementen und stellt das Paar als Array aus.
Dies ist im Diagramm einfacher zu visualisieren:
<code class="language-javascript">const task_stream = // 创建所有数据库中任务的流 getTasks(). // 只获取此用户的任务 filter((task) => task.user_id == user_id). // 获取未完成的任务 filter((task) => !task.completed). // 只获取任务名称 map((task) => task.name) /* 任务如下所示: task = { user_id : number, completed : boolean, name : string } */</code>
verwenden Sie ZIP, um nur auf Änderungen in zwei Streams zu reagieren
Warten Sie also, bis der Benutzer seine Auswahl von ID- und Endpoint -Feldern aktualisiert, und ersetzen Sie Combinelatest () durch ZIP ().
<code class="language-javascript">const task_stream = parameter_stream. debounce(1000). map((parameter) => { getTasks(). retry(3). filter((task) => task.user_id === user_id). filter((task) => task.completed === parameter). map((task) => task.name) }). flatMap(Rx.Observable.from). distinctUntilChanged(). update()</code>
im Gegensatz zu CombinElatest () wird ZIP () warten, bis beide beobachtbaren Objekte neue Inhalte ausgeben, bevor ein Array ihrer aktualisierten Werte gesendet wird.
10
<code class="language-javascript">source. map((user) => user.website)</code>Schließlich ermöglicht TakeUntil (), auf den ersten Stream zuzuhören, bis der zweite Stream Werte abgibt.
Zusammenfassung
<code class="language-javascript">source. map((user) => user.website). filter((website) => (website.endsWith('net') || website.endsWith('org')); })</code>Nur Zeitabmessungen zu Arrays öffnen die Tür für neue Denken über Programme.
rxjs ist viel mehr als das, was wir hier sehen, aber das reicht aus, um einen langen Weg zu gehen.
FAQs über RXJS -Funktionen (FAQ)
Was ist der Hauptunterschied zwischen RXJS und traditionellem JavaScript?
rxjs ist eine reaktive Programmierbibliothek, die beobachtbare Objekte verwendet, um die Kombination aus asynchronem oder Rückrufback-Code zu vereinfachen. Dies wird mit der Verwendung traditioneller JavaScript mit einem imperativeren Programmierstil verglichen. Der Hauptunterschied besteht darin, wie sie Daten verarbeiten - Rxjs behandelt Daten als Stream, das mit verschiedenen Operatoren betrieben und transformiert werden kann, während herkömmliche JavaScript -Daten linearer verarbeitet.
In RXJs können Sie mit dem neuen Observable () -Konstruktor beobachtbare Objekte erstellen. Dieser Konstruktor nimmt eine Funktion als Argument an, die als Abonnentenfunktion bezeichnet wird und bei der ursprünglich ein beobachtbares Objekt abonniert wird. Hier ist ein grundlegendes Beispiel:
<code class="language-javascript">const task_stream = // 创建所有数据库中任务的流 getTasks(). // 只获取此用户的任务 filter((task) => task.user_id == user_id). // 获取未完成的任务 filter((task) => !task.completed). // 只获取任务名称 map((task) => task.name) /* 任务如下所示: task = { user_id : number, completed : boolean, name : string } */</code>
rxjs verfügt über eine breite Palette von Operatoren, mit denen die Daten zwischen beobachtbaren Objekten und Beobachtern fließen lassen können. Einige der Hauptbetreiber umfassen MAP (), filter (), record (), merge () und concat (). Jeder dieser Bediener betreibt auf unterschiedliche Weise einen Datenstrom, z. B. Datenkonvertieren, Filtern bestimmter Werte oder das Kombinieren mehrerer Streams.
rxjs liefert mehrere Operatoren, die Fehler wie CatchError (), Wiederholung () und Wiederholung () umgehen. Der Operator CatchError () wird verwendet, um Fehler in beobachtbaren Streams zu fangen und ein neues beobachtbares Objekt zurückzugeben oder einen Fehler zu werfen. Der Retyp () -Preiber kann verwendet werden, um im Falle eines Fehlers beobachtbare Objekte erneut zu bezeichnen. Der Wiederholungstreiber () ist ähnlich, bietet jedoch mehr Kontrolle darüber, wann sie wiederholt werden müssen.
Wenn Sie ein beobachtbares Abonnement abonnieren, erhalten Sie ein Abonnement, das eine Methode für Abzahlen () enthält. Sie können diese Methode aufrufen, um die Ausführung des beobachtbaren Objekts zu stornieren und alle verwendeten Ressourcen zu bereinigen. Hier ist ein Beispiel:
<code class="language-javascript">const task_stream = parameter_stream. debounce(1000). map((parameter) => { getTasks(). retry(3). filter((task) => task.user_id === user_id). filter((task) => task.completed === parameter). map((task) => task.name) }). flatMap(Rx.Observable.from). distinctUntilChanged(). update()</code>
In RXJs kann das beobachtbare Objekt heiß oder kalt sein. Kaltobestierungen werden beim Abonnieren ausgeführt, während heiße Observablen Werte bereits vor dem Abonnieren produzieren. Mit anderen Worten, kalte beobachtbare Objekte sind inert, während heiße beobachtbare Objekte dies nicht tun.
rxjs liefert mehrere Operatoren, die mehrere beobachtbare Objekte kombinieren, wie z. B. merge (), concat (), combinelatest () und ZIP (). Jeder dieser Bediener kombiniert Datenströme auf unterschiedliche Weise, abhängig von Ihren spezifischen Anforderungen.
Das Thema in RXJS ist eine spezielle Art von beobachtbarem Objekt, mit dem mehrere Beobachter Multicasting von Werten ermöglicht werden können. Im Gegensatz zu gewöhnlichen beobachtbaren Objekten halten Themen für viele Zuhörer Register.
Angular unterstützt RXJS integriert und verwendet ihn intern für verschiedene Funktionen. Sie können RXJS auch in Ihrem eigenen Code verwenden, um asynchrone Vorgänge zu verarbeiten und Funktionen wie automatische Abschluss, De-Jitter, Drosselung, Umfragen usw. zu implementieren.
rxjs können in verschiedenen Szenarien verwendet werden, in denen asynchrone Daten erforderlich sind. Einige übliche Anwendungsfälle umfassen die Bearbeitung von Benutzereingaben, die Erstellung von HTTP -Anforderungen, die Verwendung von Websockets und die Bearbeitung von Animationen.
Das obige ist der detaillierte Inhalt von10 Notwendigkeit, RXJS-Funktionen mit Beispielen zu wissen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!