Play/Scala:并行进行未知数量的I/O调用,等待结果
所以,我读了一篇关于平行理解的文章。他给出了以下代码示例:Play/Scala:并行进行未知数量的I/O调用,等待结果,scala,concurrency,playframework-2.0,Scala,Concurrency,Playframework 2.0,所以,我读了一篇关于平行理解的文章。他给出了以下代码示例: // Make 3 parallel async calls val fooFuture = WS.url("http://foo.com").get() val barFuture = WS.url("http://bar.com").get() val bazFuture = WS.url("http://baz.com").get() for { foo <- fooFuture bar <- barFutu
// Make 3 parallel async calls
val fooFuture = WS.url("http://foo.com").get()
val barFuture = WS.url("http://bar.com").get()
val bazFuture = WS.url("http://baz.com").get()
for {
foo <- fooFuture
bar <- barFuture
baz <- bazFuture
} yield {
// Build a Result using foo, bar, and baz
Ok(...)
}
电话号码为:
def callOne(param: String): Future[Boolean] = {
// do something and return the Future with a true/false value
Future(true)
}
def callTwo(param: String): Future[Boolean] = {
// do something and return the Future with a true/false value
Future(false)
}
所以,我的问题是,我应该如何对WS调用(或数据库查询)序列的结果做出反应,以获得收益
我已经给出了两个调用的示例,但我希望相同的代码能够并行处理1到多个调用,并在yield中收集结果,以便最终继续做其他事情
重要提示:所有呼叫应并行执行,最快的呼叫将在慢速呼叫之前完成,而不考虑它们的触发顺序。很可能就是您想要的
用法示例:
val futures = List(WS.url("http://foo.com").get(), WS.url("http://bar.com").get())
Future.sequence(futures) # => Transforms a Seq[Future[_]] to Future[Seq[_]]
在输入序列中的所有期货完成之前,future.sequence的未来收益将不会完成
奖金:
如果您的未来是异构类型的,并且您需要保留该类型,那么可以使用Hlist。我已经编写了以下代码段,它将获取一个HL未来列表,并将其转换为包含一个HL已解析值列表的未来:
import shapeless._
import scala.concurrent.{ExecutionContext,Future}
object FutureHelpers {
object FutureReducer extends Poly2 {
import scala.concurrent.ExecutionContext.Implicits.global
implicit def f[A, B <: HList] = at[Future[A], Future[B]] { (f, resultFuture) =>
for {
result <- resultFuture
value <- f
} yield value :: result
}
}
// Like Future.sequence, but for HList
// hsequence(Future { 1 } :: Future { "string" } :: HNil)
// => Future { 1 :: "string" :: HNil }
def hsequence[T <: HList](hlist: T)(implicit
executor: ExecutionContext,
folder: RightFolder[T, Future[HNil], FutureReducer.type]) = {
hlist.foldRight(Future.successful[HNil](HNil))(FutureReducer)
}
}
导入无形状_
导入scala.concurrent.{ExecutionContext,Future}
对象未来助手{
对象未来2{
导入scala.concurrent.ExecutionContext.Implicits.global
隐式定义f[A,B
为了{
结果看起来像是我正在寻找的,但是,在我等待全部完成之前,如何动态地填充未来
?如果您有一个url:Seq[String |,url映射(WS.url).好的,所以我测试了Future.sequence一点,但它们是按顺序执行的,1,2,3…等等,我真的在寻找一个解决方案,一次触发所有事件,然后等待所有事件的结束。你正在寻找的正是Future.sequence所做的。换句话说,一旦你实例化它们,你的未来就会被安排好。所以,如果您实例化一个未来列表,它们将被同时调度(在ExecutionContext允许的范围内;您可能需要根据您的设备调整executor以获得更高的并行性,因为它默认为机器上2倍的内核).Future.sequence将只等待列表中的每个未来,然后向您提供结果列表(与提供的未来列表的顺序相同)。
import shapeless._
import scala.concurrent.{ExecutionContext,Future}
object FutureHelpers {
object FutureReducer extends Poly2 {
import scala.concurrent.ExecutionContext.Implicits.global
implicit def f[A, B <: HList] = at[Future[A], Future[B]] { (f, resultFuture) =>
for {
result <- resultFuture
value <- f
} yield value :: result
}
}
// Like Future.sequence, but for HList
// hsequence(Future { 1 } :: Future { "string" } :: HNil)
// => Future { 1 :: "string" :: HNil }
def hsequence[T <: HList](hlist: T)(implicit
executor: ExecutionContext,
folder: RightFolder[T, Future[HNil], FutureReducer.type]) = {
hlist.foldRight(Future.successful[HNil](HNil))(FutureReducer)
}
}