我在Akka流程中很新,我一直在使用Rx一段时间,所以我对所有运算符都很了解,但我不知道为什么我的管道没有发出值
这是我的代码
@Test def mainFlow(): Unit = {
val increase = Flow[Int]
.map(value => value * 10)
val filterFlow = Flow[Int]
.filter(value => value > 50)
.take(2)
Source(0 to 10)
.via(increase)
.via(filterFlow)
.to(Sink.foreach(value => println(s"Item emitted:$value")))
.run()
}
第一个Flow变换Source中发出的值乘以10,第二个流过滤器只获取高于50的项目然后我得到2,所以我期望在Sink 60和70中 但没有发出任何东西。
知道为什么吗?
答案 0 :(得分:3)
您的流程已正确构建,并发出您提到的那两个元素。
我相信问题出在你的考试中。也就是说,流程是异步运行的,您的测试是一个简单的Unit
过程。因此,测试不会等到流程运行。
您需要在测试中引入一些同步来执行断言。一种方法是使用ScalaTest中的ScalaFutures
特征,它为您提供futureValue
方法。
val increase = Flow[Int]
.map(value => value * 10)
val filterFlow = Flow[Int]
.filter(value => value > 50)
.take(2)
Source(0 to 10)
.via(increase)
.via(filterFlow)
.runForeach(value => println(s"Item emitted:$value"))
.futureValue
请注意,.to(Sink.foreach{...}).run()
不会公开您需要同步的Future[Done]
。您的代码需要更改为.toMat(Sink.foreach{...})(Keep.right).run()
,可以缩写为.runForeach(...)
。
答案 1 :(得分:1)
因为您所说的是以下内容:
对于数字1..10,将它们乘以10,但只产生2个第一个元素,然后保留所有大于50的元素,然后打印它们。
此外,您的测试不会等待RunnableFlow的完成,这通常意味着您的程序将在流有机会运行之前退出(Akka Streams以异步方式运行)。
请注意,对于您的示例,没有理由使用GraphDSL,您的代码与以下内容相同:
Source(1 to 10).map(_ * 10).take(2).filter(_ > 50).runForeach(println)
但是因为它并没有真正做任何“有意义的异步”,我认为你会更好:
(1 to 10).map(_ * 10).take(2).filter(_ > 50).foreach(println)
但是再次,使用代码的当前状态,它等同于以下表达式:
()