2017-06-19 17 views
8

Ich habe eine RxJS5 Pipeline wie dieseRxJS Takewhile sondern umfasst den letzten Wert

Rx.Observable.from([2, 3, 4, 5, 6]) 
    .takeWhile((v) => { v !== 4 }) 

ich das Abonnement behalten mag sieht, bis ich 4 zu sehen, aber ich mag letztes Element 4 auch im Ergebnis enthalten sein . So sollte das obige Beispiel

sein
2, 3, 4 

Doch nach official document, takeWhile Betreiber nicht inklusive ist. Das heißt, wenn es auf das Element trifft, das nicht mit dem Prädikat übereinstimmt, das wir angegeben haben, vervollständigt es den Strom sofort ohne das letzte Element. Als Ergebnis der oben genannte Code wird tatsächlich ausgegeben

2, 3 

Also meine Frage ist, was ist der einfachste Weg, das ich takeWhile sondern auch emittieren das letzte Element mit RxJS erreichen kann?

+0

Etwas witzig, aber der einfachste Weg wäre '.takeWhile (v => v <5) ' – cartant

+0

Ernster: https://github.com/martinsik/rxjs-extra/blob/master/src/operator/takeWhileInclusive.ts – cartant

Antwort

11

Im moment gibt es mindestens zwei mögliche Abhilfen:

  1. mit concatMap():

    Observable.of('red', 'blue', 'green', 'orange') 
        .concatMap(color => { 
        if (color === 'green') { 
         return Observable.of(color, null); 
        } 
        return Observable.of(color); 
        }) 
        .takeWhile(color => color) 
        .subscribe(color => console.log(color)); 
    
  2. multicast() Verwendung:

    Observable 
        .of("red", "blue", "green", "orange") 
        .multicast(
        () => new ReplaySubject(1), 
        (colors) => colors.takeWhile((c) => c !== 'green').concat(colors.take(1)) 
    ) 
    

Ich habe mit dieser Operator auch, damit ich es auf meine eigene Reihe von zusätzlichen RxJS 5 Operatoren gemacht: https://github.com/martinsik/rxjs-extra#takewhileinclusive

Dieser Operator wurde auch in der RxJS 5 Frage diskutiert: https://github.com/ReactiveX/rxjs/issues/2420

3

Wenn Ihr Vergleich ist so, dass Sie genau wissen, was ist das letzte Element (wie für !==), Sie können es selbst wieder hinzufügen:

Rx.Observable.from([2, 3, 4, 5, 6]) 
    .takeWhile((v) => v !== 4) 
    .concat(Rx.Observable.of(4)) 
    .subscribe(console.log) 
0

ich über das gleiche Problem kam, ich das letzte Element benötigt, um aufgenommen werden i für die Zeichnung einen Verweis zu halten wählte und abmelden innerhalb deronNextRückruf, wenn die Bedingung erfüllt wurde. Arbeiten mit dem Beispiel-Code wäre es:

const subscription = Observable.of('red', 'blue', 'green', 'orange') 
    .subscribe(color => { 
    // Do something with the value here 
    if (color === 'green') { 
     subscription.unsubscribe() 
    } 
    }) 

Das ist für mich gearbeitet, weil es auch die beobachtbaren emittierende Quelle zu stoppen verursacht, was ich in meinem Szenario erforderlich ist. Ich merke, dass ich nicht takeWhile Operator verwende, aber das Hauptziel erreicht ist und ohne irgendwelche Umgehungen oder zusätzlichen Code. Ich bin kein Fan der Dinge zu zwingen, auf eine Art und Weise zu arbeiten, für die sie nicht entworfen wurden. Die Nachteile davon sind:

  • Wenn andere Beobachter abonniert sind, wird die Quelle weiterhin emittieren.
  • Die onCompleted wird nicht aus irgendeinem Grund aufgerufen, wenn der letzte Beobachter abmeldet, aber ich habe überprüft, dass die Quelle tatsächlich nicht mehr emittiert.
Verwandte Themen