如何将Akka源转换为scala.stream
我已经有了一个如何将Akka源转换为scala.stream,scala,akka-stream,scala-streams,Scala,Akka Stream,Scala Streams,我已经有了一个Source[T],但我需要将它传递给一个需要流[T]的函数 我可以.run源代码并将所有内容具体化为一个列表,然后对结果执行.toStream,但这会删除我想要保留的惰性/流特性 这是实现这一目标的唯一途径还是我遗漏了什么 编辑: 在阅读了弗拉基米尔的评论后,我认为我在以错误的方式处理我的问题。下面是一个简单的示例,说明我拥有什么以及我想要创建什么: // Given a start index, returns a list from startIndex to startIn
Source[T]
,但我需要将它传递给一个需要流[T]
的函数
我可以.run
源代码并将所有内容具体化为一个列表,然后对结果执行.toStream
,但这会删除我想要保留的惰性/流特性
这是实现这一目标的唯一途径还是我遗漏了什么
编辑:
在阅读了弗拉基米尔的评论后,我认为我在以错误的方式处理我的问题。下面是一个简单的示例,说明我拥有什么以及我想要创建什么:
// Given a start index, returns a list from startIndex to startIndex+10. Stops at 50.
def getMoreData(startIndex: Int)(implicit ec: ExecutionContext): Future[List[Int]] = {
println(s"f running with $startIndex")
val result: List[Int] = (startIndex until Math.min(startIndex + 10, 50)).toList
Future.successful(result)
}
因此,getMoreData
只是模拟一个服务,它通过页面将数据返回给我。
我的第一个目标是创建以下函数:
def getStream(startIndex: Int)(implicit ec: ExecutionContext): Stream[Future[List[Int]]]
其中,流中的下一个Future[List[Int]]
元素取决于上一个元素,从流中前一个Future的值中读取最后一个索引。起始索引为0的Eg:
getStream(0)(0) would return Future[List[0 until 10]]
getStream(0)(1) would return Future[List[10 until 20]]
... etc
一旦我有了这个函数,我想创建第二个函数来进一步将它映射到一个简单的流[Int]
。例如:
def getFlattenedStream(stream: Stream[Future[List[Int]]]): Stream[Int]
Streams开始觉得对于这个工作来说是错误的工具,我应该只编写一个简单的循环。我喜欢流的想法,因为消费者可以映射/修改/使用他们认为合适的流,而不需要制作人知道它。Scala流是在
getStream
中完成任务的好方法;以下是构建您所需内容的基本方法:
def getStream(startIndex : Int)
(implicit ec: ExecutionContext): Stream[Future[List[Int]]] =
Stream
.from(startIndex, 10)
.map(getMoreData)
事情变得棘手的地方是使用getflattedstream
函数。可以消除列表[Int]
值周围的Future
包装,但它需要wait.result
函数调用,这通常是错误的
通常情况下,最好对未来进行操作,并允许异步操作自行进行。如果你分析你的最终需求/目标,通常没有必要等待未来
但是,如果你绝对必须放弃未来,那么下面是可以实现它的代码:
val awaitDuration = 10 Seconds
def getFlattenedStream(stream: Stream[Future[List[Int]]]): Stream[Int] =
stream
.map(f => Await.result(f, awaitDuration))
.flatten
Scala Streams是在
getStream
中完成任务的好方法;以下是构建您所需内容的基本方法:
def getStream(startIndex : Int)
(implicit ec: ExecutionContext): Stream[Future[List[Int]]] =
Stream
.from(startIndex, 10)
.map(getMoreData)
事情变得棘手的地方是使用getflattedstream
函数。可以消除列表[Int]
值周围的Future
包装,但它需要wait.result
函数调用,这通常是错误的
通常情况下,最好对未来进行操作,并允许异步操作自行进行。如果你分析你的最终需求/目标,通常没有必要等待未来
但是,如果你绝对必须放弃未来,那么下面是可以实现它的代码:
val awaitDuration = 10 Seconds
def getFlattenedStream(stream: Stream[Future[List[Int]]]): Stream[Int] =
stream
.map(f => Await.result(f, awaitDuration))
.flatten
我不确定这是不是个好主意。当您想要从
流中获取下一个元素,而具体化的反应流还不能提供它时,您认为您的流应该如何运行?应该如何处理错误?流
的使用者在完成具体化的反应流时应该如何关闭它?我认为回答这些问题是可能的,但由此产生的抽象将是漏洞百出和笨拙的。我创建了Source[T]
,因为我需要从url获取T
,这意味着我有一个Future[T]
。我想我应该使用mapsync
来解决这个问题。我想我真正想要的是将流[Future[T]]
转换为流[T]
,只在实际需要更多的时候调用url。我是否完全走错了方向?问题中的一些代码示例不会有什么坏处……我不确定这是否是个好主意。当您想要从流中获取下一个元素,而具体化的反应流还不能提供它时,您认为您的流应该如何运行?应该如何处理错误?流
的使用者在完成具体化的反应流时应该如何关闭它?我认为回答这些问题是可能的,但由此产生的抽象将是漏洞百出和笨拙的。我创建了Source[T]
,因为我需要从url获取T
,这意味着我有一个Future[T]
。我想我应该使用mapsync
来解决这个问题。我想我真正想要的是将流[Future[T]]
转换为流[T]
,只在实际需要更多的时候调用url。我是否完全走错了方向?问题中的一些代码示例不会有什么坏处……问题的关键在于。只有在我们提前知道索引是什么的情况下,from(startIndex,10)
才有效。然而,我想要的是,下一个指数(本例中为10)必须由上一个未来的结果确定。流中的每个步骤都必须等待前一个将来完成,然后才能进行计算。问题的关键在于。只有在我们提前知道索引将是什么的情况下,from(startIndex,10)
才能起作用。然而,我想要的是,下一个指数(本例中为10)必须由上一个未来的结果确定。流中的每个步骤都必须等待前一个将来完成,然后才能进行计算。