Ein kurzer Vortrag über Rx-responsive Programmierung

Ein kurzer Vortrag über Rx-responsive Programmierung

1. Beobachtbar

Observable bedeutet wörtlich „beobachtbar“, mit anderen Worten, es ist eine Art „Datenquelle“ oder „Ereignisquelle“. Diese Datenquelle kann beobachtet werden, was sich grundlegend vom aktiven Sammeln von Daten unterscheidet. Um eine anschauliche Metapher zu verwenden: Observable ist wie ein Wasserhahn. Sie können den Wasserhahn aufdrehen – Observable abonnieren, und dann fließt Wasser – Daten fließen kontinuierlich heraus. Dies ist die Kernidee der responsiven Programmierung – der Wechsel von aktiv zu passiv. Dies wird in diesem Artikel allerdings nicht näher erläutert.

Observable ist ein Konzept, das auf verschiedene Arten implementiert werden kann. Dieser Artikel verwendet höherwertige Funktionen, um zwei häufig verwendete Observables zu implementieren: fromEvent und Interval. Indem wir die beiden Verhaltensweisen des Abonnierens und Abbestellens von Observable erklären, können wir den Lesern helfen, wirklich zu verstehen, was Observable ist.

2. Funktionen höherer Ordnung

Das Konzept der Funktion höherer Ordnung stammt aus der funktionalen Programmierung. Eine einfache Definition ist, dass der Eingabeparameter oder Rückgabewert einer Funktion eine Funktion einer Funktion ist. Zum Beispiel:

Funktion foo(arg){
    Rückgabefunktion(){
        console.log(arg)
    }
}
const bar = foo("Hallo Welt")
bar() // hallo Welt

PS: Es gibt viele Dinge, die Funktionen höherer Ordnung tun können, und sie werden hier nur für die in diesem Artikel erforderlichen Situationen verwendet.

Der Aufruf der obigen foo-Funktion druckt „Hallo Welt“ nicht direkt, sondern speichert „Hallo Welt“ nur im Cache. Später rufen wir die zurückgegebene Balkenfunktion je nach tatsächlichem Bedarf auf und führen dann die eigentliche Arbeit zum Drucken von „Hallo Welt“ aus.

Warum müssen wir diesen Verpackungsschritt durchführen? Tatsächlich wird dadurch der Anruf „verzögert“. Und die Essenz von allem liegt im Wort „Verzögerung“. Im Wesentlichen verpacken wir ein Verhalten so, dass es wie etwas Einheitliches aussieht, etwa wie eine Lieferbox.

Es können unterschiedliche Dinge hineingelegt werden, für die Logistik ist es jedoch eine einheitliche Sache. Daher können einheitliche Vorgänge für Expresskartons gestaltet werden, wie z. B. Stapeln, Transportieren, Lagern und sogar das Öffnen des Kartons.

Um auf das vorherige Beispiel zurückzukommen: Der Aufruf der Funktion foo entspricht dem Packen eines Kurierpakets. Im Kurierpaket befindet sich ein festes Programm, das beim Öffnen des Kurierpakets (Aufrufleiste) einen Druckvorgang ausführt.

Wir können foo1, foo2, foo3 haben … es gibt verschiedene Programme darin, aber diese Foos haben eine gemeinsame Operation, nämlich „offen“. (Die Voraussetzung ist, dass foo eine Funktion zurückgibt, sodass die Operation „Öffnen“ ausgeführt werden kann, d. h. die zurückgegebene Funktion aufgerufen werden kann).

Funktion foo1(arg){
    Rückgabefunktion(){
       Konsole.log(arg+"?")
    }
}
Funktion foo2(arg){
      Rückgabefunktion(){
         Konsole.log(arg+"!")
     }
}
const bar1 = foo1("Hallo Welt")
const bar2 = foo2("ja")
bar1()+bar2() // hallo Welt? ja!

3. Express-Box-Modell

3.1. Express-Box-Modell 1: fromEvent

Vor dem Hintergrund der oben genannten Grundlagen werfen wir einen Blick auf das in der Rx-Programmierung am häufigsten verwendete Observable – fromEvent(……). Für Anfänger der Rx-Programmierung ist es zunächst schwierig, den Unterschied zwischen fromEvent(...) und addEventListener(...) zu verstehen.

btn.addEventListener("Klick",Rückruf)
rx.fromEvent(btn,"klicken").abonnieren(Rückruf)

Wenn Sie diesen Code direkt ausführen, ist der Effekt tatsächlich derselbe. Was ist also der Unterschied? Der direkteste Unterschied besteht darin, dass die Subscribe-Funktion auf fromEvent(...) statt auf btn wirkt, während addEventListener direkt auf btn wirkt. Die Abonnementfunktion ist eine Art „offener“ Vorgang und fromEvent(...) ist eine Art Expressbox.

fromEvent ist eigentlich ein "verzögerter" Aufruf von addEventListener

Funktion vonEreignis(Ziel,Ereignisname){
    Rückgabefunktion (Rückruf) {
        target.addEventListener(evtName,Rückruf)
    }
}
const ob = fromEvent(btn,"klicken")
ob(console.log) // entspricht „subscribe“

Oh! fromEvent ist im Wesentlichen eine Funktion höherer Ordnung

Wie das Abonnieren implementiert wird, um den Vorgang „Öffnen“ abzuschließen, liegt außerhalb des Rahmens dieses Artikels. In der Rx-Programmierung wird diese Abonnementaktion als „Abonnement“ bezeichnet. „Abonnement“ ist eine einheitliche Operation aller Observables. Auch in diesem Artikel ist der „Aufruf“ von Observable logisch gleichbedeutend mit „Abonnieren“.

Nehmen wir ein weiteres Beispiel, das es den Lesern grundsätzlich ermöglicht, aus zwei Beispielen N Schlussfolgerungen zu ziehen.

3.2. Expressbox-Modell 2: Intervall

In Rx gibt es ein Intervall. Was ist der Unterschied zwischen diesem und setInterval?

Ich vermute, dass jemand bereits mit der Antwort begonnen hat. Intervall ist ein verzögerter Aufruf von setInterval! Bingo!

Funktion Intervall(Periode){
    sei i = 0
    Rückgabefunktion (Rückruf) {
        setzeInterval(Zeitraum,()=>Rückruf(i++))
    }
}
const ob = Intervall(1000)
ob(console.log) // entspricht „subscribe“

Ob es sich nun um fromEvent(...) oder Interval(...) handelt, ist in den beiden obigen Beispielen zwar die interne Logik völlig unterschiedlich, sie gehören aber zum selben Thema wie die „Expressbox“, die wir als Observable bezeichnen.

fromEvent und Interval sind nur Modelle zum Erstellen von „Express-Boxen“. Nur was nach dem Aufruf zurückgegeben wird, ist die „Express-Box“, d. h. fromEvent(btn,"click"), interval(1000) usw.

4. Hochwertige Expressbox

Auf der Grundlage dieser Punkte können wir nun vorankommen: Da wir nun so viele Expresskartons haben, können wir sie neu verpacken.

Wie am Anfang des Artikels erwähnt, vereint die Expressbox einige Vorgänge, sodass wir viele Expressboxen zu einer großen Expressbox zusammenstapeln können! Diese große Express-Box verfügt über die gleiche „Öffnen“-Funktion (d. h. Abonnieren) wie die kleine Express-Box. Was passiert, wenn wir diesen großen Expresskarton öffnen?

Dabei gibt es viele verschiedene Möglichkeiten, wie beispielsweise das Öffnen der Kisten nacheinander (Concat), das Öffnen aller Kisten auf einmal (Merge) oder das Öffnen nur der Kiste, die sich am leichtesten öffnen lässt (Race).

Hier ist eine vereinfachte Version der Merge-Methode:

Funktion merge(...obs){
    Rückgabefunktion (Rückruf) {
        obs.forEach(ob=>ob(callback)) // Alle Expressboxen öffnen}
}

Nehmen wir das vorherige FromEvent und Intervall als Beispiel!

Verwenden Sie die Merge-Methode, um zwei Observables zu kombinieren:

const ob1 = fromEvent(btn,'click') // Erstelle Expressbox 1
const ob2 = interval(1000) // Erstelle Expressbox 2
const ob = merge(ob1,ob2) //Erstelle eine große Expressbox ob(console.log) //Öffne die große Expressbox

Wenn wir das große Express-Box-OB „öffnen“ (abonnieren), werden auch die beiden kleinen Express-Boxen „geöffnet“ (abonniert) und die Logik in jeder kleinen Express-Box wird ausgeführt. Wir verschmelzen die beiden Observables zu einem.

Aus diesem Grund arbeiten wir so hart daran, verschiedene asynchrone Funktionen in Observables zu kapseln – um einheitliche Operationen mit ihnen zu ermöglichen! Natürlich ist das einfache „Öffnen“ (Abonnieren) nur die grundlegendste Funktion. Wir werden uns gleich mit den erweiterten Funktionen befassen.

5. Zerstöre die Kurierbox

5.1. Zerstören Sie die Kurierbox - kündigen Sie das Abonnement

Nehmen wir fromEvent als Beispiel. Zuvor haben wir eine einfache High-Order-Funktion als Wrapper für addEventListener geschrieben:

Funktion vonEreignis(Ziel,Ereignisname){
    Rückgabefunktion (Rückruf) {
        target.addEventListener(evtName,Rückruf)
    }
}

Wenn wir diese Funktion aufrufen, wird eine Lieferbox generiert (fromEvent(btn,'click')). Wenn wir die von dieser Funktion zurückgegebene Funktion aufrufen, wird die Expressbox geöffnet (fromEvent(btn,'click')(console.log)).

Wie vernichten wir also diesen geöffneten Expresskarton?

Zuerst müssen wir eine geöffnete Kurierbox erhalten. Das Ergebnis des obigen Funktionsaufrufs ist ungültig und wir können nichts damit anfangen, also müssen wir eine geöffnete Kurierbox konstruieren. Verwenden Sie weiterhin die Idee von Funktionen höherer Ordnung: Geben Sie für Zerstörungsvorgänge eine andere Funktion in der zurückgegebenen Funktion zurück.

Funktion vonEreignis(Ziel,Ereignisname){
    Rückgabefunktion (Rückruf) {
        target.addEventListener(evtName,Rückruf)
        Rückgabefunktion(){
            Ziel.removeEventListener(evtName,Rückruf)
        }
    }
}
const ob = fromEvent(btn,'click') // Erstelle eine Kurierkiste const sub = ob(console.log) // Öffne die Kurierkiste und erhalte eine Funktion, mit der sie zerstört werden kann sub() // Zerstöre die Kurierkiste

Das Gleiche können wir auch für Intervalle tun:

Funktion Intervall(Periode){
    sei i = 0
    Rückgabefunktion (Rückruf) {
        let id = setInterval(Zeitraum,()=>Rückruf(i++))
        Rückgabefunktion(){
            Intervall löschen(id)
        }
    }
}
const ob = interval(1000) // Erstelle eine Kurierkiste const sub = ob(console.log) // Öffne die Kurierkiste sub() // Zerstöre die Kurierkiste

5.2. Zerstören Sie hochwertige Express-Boxen

Nehmen wir als Beispiel die Zusammenführung:

Funktion merge(...obs){
    Rückgabefunktion (Rückruf) {
        const subs = obs.map(ob=>ob(callback)) // Alle abonnieren und alle Zerstörungsfunktionen sammeln return function(){
            subs.forEach(sub=>sub()) // Durchlaufe die Zerstörungsfunktion und führe sie aus}
    }
}
 
const ob1 = fromEvent(btn,'click') // Erstelle Expressbox 1
const ob2 = interval(1000) // Erstelle Expressbox 2
const ob = merge(ob1,ob2) //Erstelle eine große Expressbox const sub = ob(console.log) //Öffne die große Expressbox sub() //Zerstöre die große Expressbox

Wenn wir den großen Expresskarton zerstören, zerstören wir auch alle kleinen Expresskartons darin zusammen.

6. Ergänzung

Bisher haben wir über die beiden wichtigen Vorgänge von Observable (Abonnieren und Abbestellen) gesprochen. Es ist zu beachten, dass das Abbestellen nicht auf Observable, sondern auf die "geöffnete" Expressbox (die nach dem Abonnieren von Observable zurückgegeben wird) wirkt!

Darüber hinaus verfügt Observable über zwei weitere wichtige Operationen, nämlich das Ausgeben von Ereignissen und die Vervollständigung/Ausnahme (bei diesen beiden Operationen handelt es sich um von Observable initiierte Rückrufe, die in die entgegengesetzte Richtung der Operation verlaufen und daher nicht als Operationen bezeichnet werden können).

Diese beiden Verhaltensweisen sind bei der Expressbox nicht so anschaulich. Wir können Observable mit einem Wasserhahn vergleichen. Das ursprüngliche Öffnen der Expressbox wird zum Aufdrehen des Wasserhahns, und die von uns übergebene Rückruffunktion kann mit einer Tasse zum Auffangen von Wasser verglichen werden! Da jeder bereits sehr gut mit Rückruffunktionen vertraut ist, wird in diesem Artikel nicht näher darauf eingegangen.

VII. Nachtrag

Um zusammenzufassen, was wir gelernt haben: Wir haben einige Operationen durch Funktionen höherer Ordnung „verzögert“ und ihnen einheitliche Verhaltensweisen gegeben. Beispielsweise verzögert „subscribe“ die Ausführung asynchroner Funktionen und „unsubscribe“ verzögert die Ausführung von Funktionen zur Ressourcenvernichtung auf der Grundlage des oben Gesagten.

Diese sogenannten „verzögerten“ Ausführungen sind am schwierigsten zu verstehen und stellen den grundlegendsten Teil der Rx-Programmierung hinter den Kulissen dar. Das Wesentliche von Rx besteht darin, asynchrone Funktionen zu kapseln und sie dann in vier Hauptverhaltensweisen zu abstrahieren: Abonnement, Abbestellung, Ereignisemission und Abschluss/Ausnahme.

Es gibt viele Möglichkeiten, die Rx-Bibliothek tatsächlich zu implementieren. Dieser Artikel verwendet nur die Idee von Funktionen höherer Ordnung, damit jeder das Wesen von Observable verstehen kann. In der offiziellen Version ist die Observable-Box keine Funktion höherer Ordnung, sondern ein Objekt, aber im Wesentlichen dasselbe.

Oben finden Sie eine kurze Erläuterung der Details der Rx-responsiven Programmierung. Weitere Informationen zur Rx-responsiven Programmierung finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung der einfachen Verwendung von RxJS in TypeScript
  • Implementierung verschiedener Möglichkeiten zum Kündigen von Abonnements in RxJava
  • Sprechen Sie über Ausnahmen und Behandlungsmethoden in RxJava2
  • Erfahren Sie mehr über das RxJS JavaScript-Framework Cycle.js
  • Erste Schritte mit RxJS und vorläufigen Anwendungen
  • Sie sind nicht an RxJava gewöhnt, nur weil Ihnen dieser Schlüssel fehlt (empfohlen)
  • RxJava2-Thread-Planungsmethode
  • Implementierungsprinzip für das Senden und Umschalten von RxJava-Nachrichten
  • Tutorial zur Kapselung von RxJava2 und Retrofit2 (übersichtlich, einfach und praktisch)

<<:  Optimieren Sie die Speichereffizienz von BLOB- und TEXT-Spalten in InnoDB-Tabellen

>>:  Detaillierte Erklärung zur Konfiguration einer statischen IP in Centos8

Artikel empfehlen

Lösung für 1067, wenn Mysql in Windows startet

Ich habe erst vor ein paar Tagen mit der Arbeit b...

MySQL 8.0.21-Installationstutorial unter Windows-System (Abbildung und Text)

Installationsvorschlag : Versuchen Sie, für die I...

Detaillierter Prozess der SpringBoot-Integration von Docker

Inhaltsverzeichnis 1. Demo-Projekt 1.1 Schnittste...

Mit CSS3 lässt sich ein umdrehbarer Hover-Effekt erzielen

CSS3 implementiert einen umdrehbaren Hover-Effekt...

Detaillierte Erläuterung von acht Methoden zum Korrigieren des CSS-Seitenendes

Beim Schreiben einer Seite kommt es häufig vor, d...

So packen Sie das Projekt per Idee in Docker

Viele Freunde wollten schon immer wissen, wie man...

CSS3 realisiert den verschiebbaren Zauberwürfel-3D-Effekt

Hauptsächlich verwendete Wissenspunkte: •CSS3 3D-...

Ein Artikel zum Verständnis von MySQL Index Pushdown (ICP)

Inhaltsverzeichnis 1. Einleitung 2. Grundsatz Pra...