RxJS combineLatest operator怪异行为

RxJS combineLatest operator怪异行为

问题描述:

我有一个关于RxJS combineLatest操作符的查询。我已经修改了在RxJS combineLatest operator怪异行为

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

给出的示例如下:

//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}` 
    ); 
}); 

我希望timerThree的值更改为真正位总是保持在打印如图输出片段:

"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" 

任何想法为什么t他正在发生?有没有什么办法解决这一问题?谢谢

这里需要注意的重要一点是timerThree本身不是可观察的,而是对可观察对象的引用。当您使用combineLatest时,它将组合该对象,而不是引用它的变量。因此,当您将timerThree分配给新的可观察对象时,它现在指向一个新对象,但combined仍在使用旧对象。

如果您希望能够更改timerThree的值,请尝试改为使用Subject。然后你可以通过timerThree.next推送新值。

补充约翰的回答:

this.timerThree未定义在latestValues[0] === 3的时刻,因为当一个lambda函数的this指“最近的外部范围内。

如果您要在浏览器中运行此项,this将为window对象,因此您只是将属性添加到窗口对象。

而且timerThree被定义为const的含义,如果你试图在同一对象上的重新分配它会抛出一个错误(但如上所述你分配给不同的对象。

与小提琴演奏围绕我那你想要做什么,尽管这需要努力消除重复代码的东西:

//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}` 
    ); 
}); 

通知的unsubscribe()呼吁防止先前合并计时器再次执行,以combineLatest新的呼叫和新Observable打印true

我也必须将timerThreeconst更改为let才能重新分配它。

Fiddle