我读过很多关于Scala Futures减少回调问题的文章。我有一个看起来开始有问题的代码。
val a = Future(Option(Future(Option(10))))
a.map { b =>
b.map { c =>
c.map { d =>
d.map { res =>
res + 10
}
}
}
}
如何使此代码更平坦?
//编辑@againstmethod
for{
b <- a
c <- b
d <- c
res <- d
} yield res + 10
此代码无法编译
最佳答案
您可以使用for comprehension。例如:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Stuff extends App {
val result = for {
f1 <- Future { 10 + 1 }
f2 <- Future { f1 + 2 }
} yield f2
result.onComplete(println)
}
结果将是13。
任何实现了正确的
map
和flatMap
函数的类都可以在for
中以这种方式使用。如果您不介意其他依赖项,则还可以使用scalaz之类的库,并显式使用monadic绑定(bind)使内容变平(EDIT编码了一些Option类型,以在下面解决注释):
import scalaz._
import Scalaz._
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.{Success,Failure}
object BindEx extends App {
def f1(i: String): Future[Int] = Future { i.length }
def f2(i: Int): Future[Option[Double]] = Future { Some(i / Math.PI) }
def f3(i: Option[Double]): Future[Option[Double]] = Future {
i match {
case Some(v) => Some(Math.round(v))
case _ => None
}
}
val result =
Monad[Future].point("Starting Point") >>=
f1 >>=
f2 >>=
f3
result.onComplete { x =>
x match {
case Success(value) => println("Success " + value)
case Failure(ex) => println(ex)
}
}
Await.result(result, 1 seconds)
}
最后,如果在成功之后,如果您仅具有要绑定(bind)的并行操作,则可以使用scalaz应用程序生成器:
val result = (
Future { 10 + 10 } |@|
Future { 20 - 3 } |@|
Future { Math.PI * 15 }
) { _ + _ / _}
println(Await.result(result, 1 seconds))
这将使所有3个 future 完成,然后将block应用于3个参数。
关于Scala future 回调 hell ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28343904/