物化值可以由汇和源产生。通过将源与接收器组合来创建可运行图。 Keep 定义组合时要保留的具体化值
-
Keep.right 选择接收器的具体化值
-
Keep.left 选择源的具体化值
-
Keep.both 以元组的形式选择两者
-
Keep.none 忽略两者并选择NotUsed,即表示没有具体化值的标记。
默认情况下,Keep.left 用于via、to 等操作。
以下示例突出显示了这一点
给定一个Source[Int, String] 和一个Sink[Int, Future[Int]]
val source: Source[Int, String] = Source(List(1, 2, 3)).mapMaterializedValue(_ => "Source Mat Value")
val sink: Sink[Int, Future[Int]] = Sink.fold(0)(_ + _)
我们可以结合source 和sink 来创建具有不同物化值的可运行图。
val left: String = source.to(sink).run() //same as toMat(...)(Keep.left)
val right: Future[Int] = source.toMat(sink)(Keep.right).run()
val both: (String, Future[Int]) = source.toMat(sink)(Keep.both).run()
现在,如果我们运行它并打印它产生的每个物化值
left=Source Mat Value
right=Future(Success(6))
both=(Source Mat Value,Future(Success(6)))
请不要将物化值与流元素的处理混为一谈。
考虑关注fold 阶段
val flowFold: Flow[Int, Int, NotUsed] = Flow[Int].fold(0)(_ + _)
val sinkFold: Sink[Int, Future[Int]] = Sink.fold(0)(_ + _)
flowFold 将fold 函数应用于流中的每个元素,并将表示fold 结果的一个 值推送到下游。如果需要,可以进一步处理此元素。
而sinkFold 是图中的最后阶段,它不能将元素推向下游。当graph处理完所有元素并完成时,它使用物化值Future[Int]返回fold结果。
如果Flow.fold 的值为55,这应该是流的具体化值而不是NotUsed。
不,值55 不是物化值。它作为一个元素被推送到下游接收器。
您可以在Sink.head 的帮助下将55 元素“捕获”到具体化的值中
val flow: Flow[Int, Int, NotUsed] = Flow[Int].fold(0)(_ + _)
val alternativeFoldSink: Sink[Int, Future[Int]] = flow.toMat(Sink.head)(Keep.right)
每个阶段都可以产生物化价值然后(为什么)不能Flow.fold
产生物化的价值。
是的,每个阶段都可能产生物化价值。但是Flow.fold 的设计目的是不这样做。大多数Flow 定义不提供具体化值。如果你想使用物化值和fold,我建议使用Sink.fold