不明白如何在kotlin中使用flux订阅

时间:2017-12-18 15:15:04

标签: spring kotlin reactive-programming project-reactor

我是反应式编程的新手。我希望看到

test provider started
Beat 1000
Beat 2000

在日志中但只有test provider started且没有Beaton complete条消息。看起来我想念一些

@Service
class ProviderService {

    @PostConstruct
    fun start(){
        val hb: Flux<HeartBeat> = Flux.interval(Duration.ofSeconds(1)).map { HeartBeat(it) }
        val provider = Provider("test", hb)
    }

}
////////////////////////

open class Provider(name: String, heartBests: Flux<HeartBeat>) {
    companion object {
        val log = LoggerFactory.getLogger(Provider::class.java)!!
    }

    init {
        log.info("$name provider started")
        heartBests.doOnComplete { log.info("on complete") }
        heartBests.doOnEach { onBeat(it.get().number) }
    }

    fun onBeat(n: Number){
        log.info("Beat $n")
    }
}

/////
class HeartBeat(val number: Number)

2 个答案:

答案 0 :(得分:2)

在您的代码lambda中来自&#39; doOnComplete&#39;从来没有被称为,因为你创造了无限的流。方法&#39; doOnEach&#39; as&#39; map&#39;是中间操作(如流中的map),它不会进行调用。 你还有另外一个错误,反应暗示&#34;流畅的模式&#34;。

试试这个简单的例子:

import reactor.core.publisher.Flux
import java.time.Duration

fun main(args: Array<String>) {
    val flux = Flux.interval(Duration.ofSeconds(1)).map { HeartBeat(it) }

    println("start")

    flux.take(3)
            .doOnEach { println("on each $it") }
            .map { println("before map");HeartBeat(it.value * 2) }
            .doOnNext { println("on next $it") }
            .doOnComplete { println("on complete") }
            .subscribe { println("subscribe $it") }

    Thread.sleep(5000)
}

data class HeartBeat(val value: Long)

答案 1 :(得分:2)

这里有三个相当常见的错误:

  • doOnEach之类的运算符返回一个具有添加行为的新Flux实例,因此您需要(重新)分配给变量或使用流畅的样式
  • 在您subscribe()(或其变体。blockXXX之后也会subscribe引发任何事情之前不会发生任何事情......)
  • 此类管道完全异步,并且由于源Thread的时间维度而在单独的interval上运行。因此,即使您已订阅,控制也会立即返回init,可能导致主线程然后退出应用程序。