windowCount丢弃值

时间:2016-10-01 10:47:41

标签: reactive-programming rxjs5

我尝试使用windowCount将可观察值分组,并为每个组发送请求的每个值。
然后,连接这些组,以便下一组的请求无法启动在当前组的请求未完成之前。
问题是某些值被跳过。

这是我的代码。
(我' m没有在这里进行实际的ajax调用,但是Observable.timer应该用于示例)。

Observable.interval(300)
     .take(12)
     .windowCount(3)
     .concatMap(obs => {
         return obs.mergeMap(
             v => Observable.timer(Math.random() * 1500).mapTo(v)
         );
     })
     .do(v => console.log(v))
     .finally(() => console.log('fin'))
     .subscribe();

我尝试通过手动创建组来替换windowCount。而且效果很好。不会跳过任何值。

Observable.interval(900)
    .take(4)
    .map(i => Observable.interval(300).take(3).map(j => j + i * 3))
    .concatMap(obs => {
        return obs.mergeMap(
            v => Observable.timer(Math.random() * 1500).mapTo(v)
        );
    })
    .do(v => console.log(v))
    .finally(() => console.log('fin'))
    .subscribe();

我的印象是windowCount应该以相同的方式对发射的值进行分组。
但是,显然它会做其他事情。

我会非常感谢对其行为的任何解释。

谢谢!

1 个答案:

答案 0 :(得分:0)

缺少的值是使用热的可观察量(Observable.interval(300))继续输出您未存储以供使用的值。

以下是您的代码的略微简化版本,它还记录了数字的发布时间。我将Math.random()替换为1,以便输出具有确定性。我还在jsbin中加载了代码供您试用:

https://jsbin.com/burocu/edit?js,console

Observable.interval(300)
    .do(x => console.log(x + ") hot observable at: " + (x * 300 + 300)))
    .take(12)
    .windowCount(3)
    .do(observe3 => {observe3.toArray()
      .subscribe(x => console.log(x + " do window count at: " + (x[2] * 300 + 300)));})
    .concatMap(obs => {
        return obs.mergeMap(
            v => Observable.timer(1 * 1500).mapTo(v)
        )
        .do(v => console.log(v + " merge map at: " + (v * 300 + 300 + 1500)));
    })
    .finally(() => console.log('fin windowCount'))
    .subscribe();

导致下面的输出。请注意,当其他运算符仍在处理时,热点可观测值会继续前进。

这就是让您感觉价值被放弃的印象。你可以看到windowCount(3)正在做你认为的,而不是

"0) hot observable at: 300"
"1) hot observable at: 600"
"2) hot observable at: 900"
"0,1,2 do window count at: 900"
"3) hot observable at: 1200"
"4) hot observable at: 1500"
"5) hot observable at: 1800"
"3,4,5 do window count at: 1800"
"0 merge map at: 1800"
"6) hot observable at: 2100"
"1 merge map at: 2100"
"7) hot observable at: 2400"
"2 merge map at: 2400"
"8) hot observable at: 2700"
"6,7,8 do window count at: 2700"
"9) hot observable at: 3000"
"10) hot observable at: 3300"
"11) hot observable at: 3600"
"9,10,11 do window count at: 3600"
" do window count at: NaN"
"8 merge map at: 4200"
"fin windowCount"

修改:进一步说明......

windowCount(3)之后,系统会调用concatMapconcatMapmapconcatAll的组合。

concatAll

  

连接源发出的每个Observable(更高阶   可观察的),以连续的方式。它订阅了每个内心   Observable 仅在前一个内部Observable完成(强调添加)之后,和   将所有值合并到返回的observable中。

所以,看看上面的输出,我们看到第一个windowCount(3)值[0,1,2]在1800到2400之间发出。

请注意,第二个windowCount(3)值[3,4,5]是在1800发出的。concatAll在[3,4,5]发出时尚未准备订阅,因为之前的内部Observable还没有完成。所以这些价值被有效地贬低了。

接下来,请注意前一个内部Observable [0,1,2]在2400完成。concatAll订阅2400。

出现的下一个值是2700处的值8(订阅从2400开始后300ms)。然后,值{8}由mergeMap在4200处输出,因为从订阅起始点2400开始的间隔延迟为300,然后是1500的定时器延迟(即2400 + 300 + 1500 = 4200)。

在此之后,序列完成,因此不会再发出任何值。

如果需要更多说明,请添加评论。