【问题标题】:RxJS combineLatest operator weird behaviourRxJS combineLatest 运算符的奇怪行为
【发布时间】:2017-08-18 21:38:08
【问题描述】:

我有一个关于 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,如输出 sn-p 所示:

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

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

【问题讨论】:

    标签: javascript angular rx-java rxjs5


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      补充约翰的回答:

      this.timerThreelatestValues[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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-29
        • 1970-01-01
        • 2013-10-29
        • 2012-12-01
        • 2015-02-01
        相关资源
        最近更新 更多