我试图找到一种更优雅的方法来执行两次函数,该函数返回Future [HttpReponse],然后使用2端调用的响应。
for {
// function post returns a Future[HttpResponse]
response <- post(uri, payload) // 1st
response <- post(uri, payload) // 2end
} yield {
// do something with the 2end response
}
这不起作用:
for {
2 times response <- post(uri, payload)
} yield {
// response becomes of type Any instead of HttpResponse
}
答案 0 :(得分:2)
If you need to make two sequential calls to a method that returns Future
, you can use flatMap
.
post(uri, payload).flatMap(_ => post(uri, payload))
This will not start the second post
operation until the first one completes.
If you have multiple chained calls you can use foldLeft
on a Range
to apply this the appropriate number of times:
(0 to N-1).foldLeft(post(uri, payload)){
case (prev, _) => prev.flatMap(_ => post(uri, payload))
}
In practice you would probably use the value from the Range
to track progress on this operation rather than discarding it.
答案 1 :(得分:1)
理想情况下,您需要这样的东西:
Future.sequence(Stream.fill(n)(post(uri, payload)))
但是,如果您真的希望它是连续的,则此操作不起作用,因为Future.sequence
急切地评估Stream
并并行开始所有期货。对于该问题here,有一些解决方案。例如,here's用户eagle yuan的顺序版本可以顺序工作:
def seq[A, M[X] <: TraversableOnce[X]](in: M[() => Future[A]])(implicit cbf: CanBuildFrom[M[()=>Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = { in.foldLeft(Future.successful(cbf(in))) { (fr, ffa) => for (r <- fr; a <- ffa()) yield (r += a) } map (_.result()) }
您可以像这样使用它:
seq(Seq.fill(n)(() => post(uri, payload)))
答案 2 :(得分:0)
这应该是全部:
val result = Seq.fill(2)(post(uri, payload)).last
我使用以下代码对此进行了测试:
val result = Seq.fill(2)(dummyFut()).last
def dummyFut(): Future[Long] = Future.successful{
Thread.sleep(1000L)
println(System.currentTimeMillis())
System.currentTimeMillis()
}
result.foreach(println)
此打印:
1552852972738
1552852973749
1552852973749