具有超时的RxScala递归流

时间:2015-03-18 18:56:01

标签: scala reactive-programming rx-java rx-scala

我试图递归地定义一个observable,它既可以从主题中发出项目,也可以在一定时间内通过默认值,在这种情况下,我使用的是计时器的默认值零。我正在使用RxScala并开始使用以下代码:

val s = PublishSubject[Int]()

def o: Observable[Unit] = {
  val timeout = Observable.timer(1 second)
  Observable.amb(s, timeout)
    .first
    .concatMap((v) => {
      println(v)
      o
    })
}

ComputationScheduler().createWorker.schedule {
  var value = 0
  def loop(): Unit = {
    Thread.sleep(5000)
    s.onNext(value + 1)
    value += 1
    loop()
  }
  loop()
}

o.toBlocking.last

这似乎应该可行,但输出令人困惑。每隔一个零序列包含两个而不是预期的四个。发出两个零,剩余的三秒钟过去,但没有输出。

0
0
0
0
1
0
0
2
0
0
0
0
3
0
0
4
0
0
0
0
5
0
0
6
0
0
0
0
7
0
0
8

2 个答案:

答案 0 :(得分:0)

这个确实令人费解!所以这是一个理论:

  1. 事实上,你的代码每5秒生成4个滴答,而不是5。
  2. 第4场比赛有一场比赛,第一场比赛是超时,然后是工作人员,然后是超时等等。
  3. 所以,而不是序列为00001 002 00003 ...将其视为0000 1002 0000 ...

    所以你可能在这里遇到两个不同的问题而且我不能在不摆弄它的情况下做很多事情,但你可以尝试的事情:

    1. 在o()中添加一个序列号,这样你就可以看到哪些时间没有赢得比赛。
    2. 将值从1秒和5秒更改为彼此不是多个的值,例如1.5和5.这可能有助于您解决一个问题并专注于另一个问题。
    3. 将一个不相关的外部工人打印出来" ----"每一秒。 0.3秒左右后启动它。可能会让你更好地了解鸿沟的位置。

答案 1 :(得分:0)

将代码重构为以下内容会产生预期结果(在我的机器上):

object Test {
  def main(args: Array[String]) {
    val s = PublishSubject[Int]()

    val timeout = Observable.timer(1 second)

    def o: Observable[Unit] = {
      Observable.amb(s, timeout).first
        .concatMap((v) => {
          println(v)
          o
        })
    }

    var value = 0
    NewThreadScheduler().createWorker.scheduleRec {
      Thread.sleep(5000)
      value += 1
      s.onNext(value)
    }

    o.toBlocking.last
  }
}

注意切换到NewT​​hreadScheduler并使用scheduleRec方法而不是手动递归调度。