我正在尝试找到一种更优雅的方式来执行2倍返回未来[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
}
如果您需要对返回Future
的方法进行两个顺序调用,则可以使用flatMap
。
post(uri, payload).flatMap(_ => post(uri, payload))
这不会启动第二个post
操作,直到第一个操作完成。
如果您有多个链式电话,则可以在Range
上使用foldLeft
来应用此适当次数:
(0 to N-1).foldLeft(post(uri, payload)){
case (prev, _) => prev.flatMap(_ => post(uri, payload))
}
实际上,您可能会使用Range
的值来跟踪此操作的进度而不是丢弃。
这应该全部:
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
理想情况下,您想要这样的东西:
Future.sequence(Stream.fill(n)(post(uri, payload)))
但是,如果您真的希望它是顺序的,则无效,因为Future.sequence
急切地评估Stream
并并行启动所有期货。这里有一些解决方案。例如,此处是用户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)))