使用 for-comp 处理期货,但如果条款使事情变得困难

Handling futures with for-comp, but if clauses are making things difficult

我发现我 运行 进入了下面的模式分配,但我无法让它工作或看起来不错的风格。

我有一个理解是 return Futures,然后我构建我的模型以在视图中显示。但是在我 return 我的操作中的结果之前,我有时不得不使用 if 子句进行分支并可能加载更多数据。

下面的代码目前无法编译,你建议我怎么做才能让下面的代码遵循这种模式的正确风格?

它无法编译,因为 compr 的内部是 return 一个 Future[Option[Something]] 但我已经将 c 定义为 Option[Something]

for {
  a <- fooService.getA()
  b <- fooService.getB()
} yield {
  var c: Option[Something] = None
  if(a.size > 0) {
    c = for {
      c <- fooService.getC()
    } yield {
      Some(c)
    }
  }
}
val model = FooModel(a, b, c)
Ok(views.html.foo.show(model))

我的视图模型定义为:

FooModel(a: A, b: B, c: Option[Something])

这看起来相当清楚:

for {
  a <- fooService.getA()
  b <- fooService.getB()
  c <- if (a.nonEmpty) fooService.getC() else Future.successful(None)
} yield {
  val model = FooModel(a, b, c)
  Ok(views.html.foo.show(model))
}

如果需要,将 if (a.nonEmpty) fooService.getC() else Future.successful(None) 提取到另一个方法或服务。

现在可以编译了,但是你有没有注意到,你的程序是顺序运行的?

object fooService{
  def getA() = {
    Future{
      println("I'm getA")
      for(i <- 1 to 10){
        println(".")
        Thread.sleep(200)
      }
      "A"
    }
  }
  def getB() = {
    Future{
      println("I'm getB")
      for(i <- 1 to 10){
        println(".")
        Thread.sleep(200)
      }
      "B"
    }
  }
}

object Main {
  def main(args: Array[String]) ={
    for {
      a <- fooService.getA()
      b <- fooService.getB()
    } println(a + b)

    Thread.sleep(4000)
  }
}

这是输出:

I'm getA
.
.
.
.
.
.
.
.
.
.
I'm getB
.
.
.
.
.
.
.
.
.
.
AB

稍作改动:

object fooService{
  def getA() = {
    Future{
      println("I'm getA")
      for(i <- 1 to 10){
        println(".")
        Thread.sleep(200)
      }
      "A"
    }
  }
  def getB() = {
    Future{
      println("I'm getB")
      for(i <- 1 to 10){
        println(".")
        Thread.sleep(200)
      }
      "B"
    }
  }
}

object Main {
  def main(args: Array[String]) ={
    val f1 = fooService.getA()
    val f2 = fooService.getB()
    for {
      a <- f1
      b <- f2
    } println(a + b)

    Thread.sleep(4000)
  }
}

输出:

I'm getA
I'm getB
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
AB