2017-08-18 6 views
4

Ich habe eine Abfrage in Bezug auf RxJS combineLatest Operator. Ich habe das Beispiel inRxJS combineLatest Betreiber seltsames Verhalten

https://www.learnrxjs.io/operators/combination/combinelatest.html

gegeben wie folgt geändert:

//timerOne emits first value at 1s, then once every 4s 
const timerOne = Rx.Observable.timer(1000, 4000); 
//timerTwo emits first value at 2s, then once every 4s 
const timerTwo = Rx.Observable.timer(2000, 4000) 
//timerThree emits first value at 3s, then once every 4s 
const timerThree = Rx.Observable.of(false); 

//when one timer emits, emit the latest values from each timer as an array 
const combined = Rx.Observable 
.combineLatest(
    timerOne, 
    timerTwo, 
    timerThree 
); 

const subscribe = combined.subscribe(latestValues => { 
    //grab latest emitted values for timers one, two, and three 
    const [timerValOne, timerValTwo, timerValThree] = latestValues; 


    if(latestValues[0] === 3) {  
    this.timerThree = Rx.Observable.of(true); 
    } 

    console.log(
    `Timer One Latest: ${timerValOne}, 
    Timer Two Latest: ${timerValTwo}, 
    Timer Three Latest: ${timerValThree}` 
    ); 
}); 

ich den Wert von timerThree erwarten wahr ändern Bit halten sie immer auf den Druck falsch wie in das Ausgabesnippet:

"Timer One Latest: 3, 
Timer Two Latest: 2, 
Timer Three Latest: false" 
"Timer One Latest: 3, 
Timer Two Latest: 3, 
Timer Three Latest: false" 
"Timer One Latest: 4, 
Timer Two Latest: 3, 
Timer Three Latest: false" 

Irgendeine Idee warum t ist es passiert? Gibt es eine Möglichkeit, das zu beheben? Danke

Antwort

2

Die wichtige Sache, von hier zu beachten ist, dass timerThree ist nicht in sich selbst beobachtbar, aber eher ein Verweis auf ein beobachtbares Objekt. Wenn Sie combineLatest verwenden, wird dieses Objekt kombiniert, nicht die Variable, die darauf verweist. Wenn Sie also timerThree einer neuen Observablen zuweisen, wird jetzt auf ein neues Objekt verwiesen, aber combined verwendet immer noch die alte.

Wenn Sie den Wert von timerThree ändern können, versuchen Sie stattdessen eine Subject. Dann können Sie mit timerThree.next neue Werte dorthin schieben.

2

Ergänzung auf Johns Antwort:

this.timerThree wird zur Zeit von latestValues[0] === 3, weil, wenn innerhalb einer Lambda-Funktion nicht definiert die this zum nächsten Ort äußeren Umfang bezieht.

Wenn Sie dies im Browser ausführen, wäre das this das Objekt window und Sie fügen lediglich eine Eigenschaft zum Fensterobjekt hinzu.

Auch ist timerThree als const Bedeutung definiert, dass er einen Fehler aus, wenn Sie eine Neuzuweisung auf demselben Objekt versuchen (aber Sie zu einem anderen Objekt zuweisen, wie oben erläutert.

Herumspielen mit Geige bekam ich etwas, das tut, was Sie wollen, obwohl diese Arbeit Code-Duplizierung entfernen muss:

//timerOne emits first value at 1s, then once every 4s 
const timerOne = Rx.Observable.timer(1000, 4000); 
//timerTwo emits first value at 2s, then once every 4s 
const timerTwo = Rx.Observable.timer(2000, 4000) 
//timerThree emits first value at 3s, then once every 4s 
let timerThree = Rx.Observable.timer(3000, 4000) 

//when one timer emits, emit the latest values from each timer as an array 
let combined = Rx.Observable 
.combineLatest(
    timerOne, 
    timerTwo, 
    timerThree 
); 

const subscribe = combined.subscribe(latestValues => { 
    //grab latest emitted values for timers one, two, and three 
    const [timerValOne, timerValTwo, timerValThree] = latestValues; 

    if(latestValues[0] === 3) { 
    console.log("this ===>", this); 
    console.log("this.timerThree ===> ", this.timerThree); 
    subscribe.unsubscribe(); 
    combined = Rx.Observable.combineLatest(timerOne, timerTwo, Rx.Observable.of(true)); 
    combined.subscribe(lvs => { 
     const [tv1, tv2, tv3] = lvs 
     console.log(
     `Timer One Latest: ${tv1}, 
     Timer Two Latest: ${tv2}, 
     Timer Three Latest: ${tv3}` 
     ); 
    }) 
    } 
    console.log(
    `Timer One Latest: ${timerValOne}, 
    Timer Two Latest: ${timerValTwo}, 
    Timer Three Latest: ${timerValThree}` 
    ); 
}); 

Hinweis der unsubscribe() Aufruf, die zuvor kombinierten Timer von der Ausführung wieder, um den neuen Anruf combineLatest und die neue Observable drucken zu verhindern true.

Ich musste auch timerThree von const zu let ändern, um es neu zuweisen zu können.

Fiddle