Scala Akka溪流通过

Scala Akka溪流通过,scala,akka-stream,Scala,Akka Stream,流可以通过以下方式与连接: def aToB: Flow[A, B, NotUsed] = { ??? } def bToC: Flow[B, C, NotUsed] = { ??? } def aToC: Flow[A, C, NotUsed] = { aToB.via(bToC) } 我想做与平面地图相当的flatMap: def aToSomeB: Flow[A, Some[B], NotUsed] = { ??? } def aToSomeC: Flow[A, Some

流可以通过以下方式与
连接:

def aToB: Flow[A, B, NotUsed] = { ??? }  
def bToC: Flow[B, C, NotUsed] = { ??? }  
def aToC: Flow[A, C, NotUsed] = { aToB.via(bToC) }  
我想做与平面地图相当的
flatMap

def aToSomeB: Flow[A, Some[B], NotUsed] = { ??? }  
def aToSomeC: Flow[A, Some[C], NotUsed] = { aToSomeB.flatVia(bToC) }

是否有一些内置的方法来执行flatVia
?这似乎是一种常见的需求,比如
选项
展开和错误平坦化。

这取决于您是否有兴趣保留那些
选项,或者是否想将它们扔掉

当您将流输入为
flow[A,Some[C],NotUsed]
is时,您似乎对
None
s一点也不感兴趣。这意味着您可以使用
collect
轻松过滤掉它们,例如:

def aToSomeC: Flow[A, C, NotUsed] = { aToSomeB.collect{case Some(x) ⇒ x}.via(bToC) }
否则,如果您需要跟踪
None
s(或
Left
s,如果您正在处理
s),您需要自己编写“提升”阶段。这可以写得相当笼统。例如,它可以写成一个函数,它接受任何流
flow[I,O,M]
,并返回另一个流
flow[E,I],E,O],M
。因为它需要扇出和扇入阶段,所以需要使用GraphDSL

  def liftEither[I, O, E, M](f: Flow[I, O, M]): Graph[FlowShape[Either[E, I], Either[E, O]], M] =
    Flow.fromGraph(GraphDSL.create(f) { implicit builder: GraphDSL.Builder[M] => f =>

      val fIn      = builder.add(Flow[Either[E, I]])
      val p        = builder.add(Partition[Either[E, I]](2, _.fold(_ ⇒ 0, _ ⇒ 1)))
      val merge    = builder.add(Merge[Either[E, O]](2))
      val toRight  = builder.add(Flow[O].map(Right(_)))

                 p.out(0).collect{case Left(x) ⇒ Left(x)}             ~> merge
      fIn.out ~> p.in
                 p.out(1).collect{case(Right(x)) ⇒ x} ~> f ~> toRight ~> merge

      new FlowShape(fIn.in, merge.out)
    })
可按照以下要求使用

  def aToSomeB: Flow[A, Either[Throwable, B], NotUsed] = ???
  def aToSomeC: Flow[A, Either[Throwable, C], NotUsed] = aToSomeB.via(liftEither(bToC))

请注意,
选项
s可以很容易地转换为
s,以利用相同的助手功能。

谢谢。我有点惊讶,这里面没有内置的东西;平坦化一系列的Eithers或Optionals不是一个共同的需求吗?我同意这是一个共同的需求,特别是如果你想让你的流阶段“参考透明”的话。然而,akka stream在某种程度上是一个较低级别的工具包,它的应用程序太多,因此很难清楚地定义哪些应该是它的一部分,哪些不应该。。