2016-11-17 6 views
1

Ich habe zwei Ereignisströme:Rxjs: Wie abonniere ich ein Ereignis nur, wenn vorher ein anderes Ereignis passiert ist?

let mouseDowns = Rx.Observable.fromEvent(document.body, "mousedown"); 
let mouseUps = Rx.Observable.fromEvent(document.body, "mouseup"); 

Ich mag alle mouseUps abonnieren, die von einem mouseDown- vorangestellt wurden.

Normalerweise würde ich nur daran erinnern, einen Zustand wie so:

let isDown = false; 
mouseDowns.subscribe(() => down = true); 
mouseUps.filter(() => isDown).subscribe(() => console.log("CAPTURED"); 

Das fühlt sich eher un- „reaktiv“ ... Was ist ein eleganter Weg, um die gleiche Sache zu tun?

Antwort

0

Ok, ich glaube, ich alleine ....

mouseDowns.map(() => mouseUps.first()).concatAll().subscribe(e => console.log(e)); 
+0

Das ist gute Arbeit! –

1

Ich glaube, du bist für skipUntil

http://jsbin.com/tawide/edit?js,console,output

const mouseDowns = Rx.Observable.fromEvent(document.body, "mousedown"); 
const mouseUps = Rx.Observable.fromEvent(document.body, "mouseup"); 

mouseUps 
    .skipUntil(mouseDowns) 
    .subscribe(x => console.log("CAPTURED")) 

suchen (Für mein eigenes Wissen, wenn eine Maus nach oben nicht durch eine Maus ging nach unten?)

EDIT

Das obige ist eine Antwort auf Ihren Code. Wenn Sie nur ein einzelnes Ereignis nach einem Down-up-Ereignis wollen, brauchen Sie einen etwas hässlichen Scan.

// dn: ---d-------d-d----d-| 
// up: u----u--u-------u---| 

// : -----e----------e---| 
const mouseUp = document.querySelector('.mouseUp'); 
const mouseDown = document.querySelector('.mouseDown'); 
const mouseUp$ = Rx.Observable.fromEvent(mouseUp, 'click') 
    .map(() => false); 
const mouseDown$ = Rx.Observable.fromEvent(mouseDown, 'click') 
.map(() => true); 
Rx.Observable.merge(mouseUp$, mouseDown$) 
    .scan((acc, cur) => { 
     if (!cur && acc.downEvent) return ({ event: true, downEvent: false}) 
     if (cur) return ({ event: false, downEvent: true}) 
     return ({ event: false, downEvent: acc.downEvent}) 
     }, {event: false, downEvent: false}) 
    .filter(x => x.event === true) 
    .subscribe(
     x => console.log('event!'), 
    (e) => console.log("error",e), 
    () => console.log('complete') 
); 
+0

Hinweis dachte es nur, dass die die Semantik von 'skipUntil()', dass sich nach einer mouseDown- OnNext alle emittiert wird, Nach MouseUp onNext wird unabhängig davon ausgegeben, wenn sie es sind wieder vor einem mouseDown-Ereignis –

+0

Bitte beachten Sie, dass ich die Semantik festgestellt habe, als ich die ursprüngliche Notiz machte. Beachten Sie, dass es genau nachahmt, was sein Beispielcode tut. –

+0

@ D.Walsh: Vielen Dank für Ihre Antwort! Um deine Frage zu beantworten: "Wann wird eine Maus nicht von einer Maus nach unten bewegt?": Das ist einfach ... wenn die Maus beim Drücken von Strg + R gedrückt wird ;-) Oder realistischer: Mausklick -> über das Element bewegen (wenn nicht der ganze Körper) -> Mouseup ... Aber ich bin nicht wirklich an Mouse-Ups und Mouse-Downs interessiert ... es war eher eine allgemeine Frage - ich bin ein Neuling bei rxjs und versuche zu verstehen was es kann und kann nicht. Werde deine Lösung morgen versuchen! Danke – Wolfgang

1

Es hängt davon ab, ob Sie aufhören wollen, Maus-Ups bis zum nächsten Mausklick zu hören. Ich meine, wenn Sie Ziel ist es, eine beobachtbare zu haben, dass Sie, wenn Sie die Maus nach unten ist sagt, Sie so etwas wie tun würde:

const isMouseDown = Rx.Observable 
    .merge(
     mouseDowns.map(() => true), 
     mouseUps.map(() => false)) 
    .startWith(false); 

isMouseDown.subscribe(state => console.log("is mouse down? " + state)); 

Wenn Sie nach einem nach unten/oben auslösen soll dann würden Sie tun :

const myClicks = mouseDowns.switchLatest(() => mouseUps); 
myClicks.subscribe(() => console.log("down/up triggered")); 
Verwandte Themen