Frage

Ich lerne reaktive Bananen und beabsichtige, sie in einer serverseitigen App zu verwenden. Ich habe einige Hintergrundinformationen zu RxJs, daher bin ich es gewohnt, dort Ereignisse mit verschiedenen Kombinatoren zu kombinieren. Also begann ich mit einfachen Beispielen für Ereigniskombinatoren. Ich habe versucht, ein einfaches Beispiel für eine reaktive Banane zu erstellen, das zwei ganzzahlige Ereignisse zu einem Summenereignis kombiniert. Ich verstehe, dass ich, um Werte aus verschiedenen Ereignissen kombinieren zu können, sie zuerst zu Verhalten machen muss, die Kombination mache und das schließlich zu einem neuen Ereignis mache. So habe ich es gemacht:

-- Behaviors from Events e1, e2
let b1 = stepper 0 e1 :: Behavior Int
let b2 = stepper 0 e2 :: Behavior Int

-- Sum Behavior
let sumB = (+) <$> b1 <*> b2
-- Back to Event
let sumE = sumB <@ (e1 `union` e2)

Ein vollständig ausführbares Beispiel finden Sie unter Gist 1594917 .

Das Problem hierbei ist, dass das sumE-Ereignis zwar korrekt ausgelöst wird, wenn in einem der Ereignisse (e1, e2) ein neuer Wert angezeigt wird, jedoch einen veralteten Wert enthält. Dies liegt anscheinend daran, wie Stepper funktioniert (der Wert des Verhaltens ändert sich "geringfügig nach" dem Auftreten des Ereignisses). Ich habe versucht, Verhalten durch Diskret zu ersetzen, mit dem gleichen Ergebnis.

Gibt es eine einfache Möglichkeit, diese Art von Ereigniskombinatoren ordnungsgemäß zu verwenden?

War es hilfreich?

Lösung

Ihre Diagnose ist genau richtig.Hier sind zwei Optionen: Sie können über changes von Discrete zu einem Ereignis zurückkehren oder akkumulierende Ereignisse erstellen.

Das Zurückarbeiten von Discrete ist wahrscheinlich einfacher (und würde ich empfehlen).Mach einfach

-- Discretes from Events e1, e2
let d1 = stepperD 0 e1 :: Discrete Int
let d2 = stepperD 0 e2 :: Discrete Int

-- Sum Discrete
let sumD = (+) <$> d1 <*> d2
-- Back to Event
let sumE = changes sumD

Jetzt wird der sumE immer aktualisiert, wenn sich der e1 oder der e2 ändert.

Die Alternative verwendet nur Ereignisse, indem eingehende Ereignisse in akkumulierende Funktionen umgewandelt werden.Es klingt komplex, aber der Code ist ziemlich einfach.

--convert each input into an accumulating tuple
let e1' = (\l (_,r) -> (l,r)) <$> e1
let e2' = (\r (l,_) -> (l,r)) <$> e2

let sumE = uncurry (+) <$> accumE (0,0) (e1' `union` e2')

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top