RxJS结合了最简单的运算符奇怪的行为

时间:2017-08-18 21:38:09

标签: javascript angular rx-java rxjs5

我有关于RxJS combineLatest运算符的查询。我修改了

中给出的示例

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的值更改为 true 位,它始终保持打印 false ,如输出片段所示:

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

知道为什么会这样吗?有没有什么办法解决这一问题?感谢

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

对John的回答补充:

this.timerThree时,

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

如果你在浏览器中运行它,this将是window对象,所以你只是在窗口对象中添加一个属性。

同样timerThree被定义为const,这意味着如果您尝试在同一个对象上重新分配,它将引发错误(但您如上所述,您正在分配给不同的对象。< / p>

玩弄小提琴我得到的东西可以做你想要的东西,虽然这需要工作来删除代码重复:

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