【问题标题】:Handling futures with for-comp, but if clauses are making things difficult用 for-comp 处理期货,但 if 子句让事情变得困难
【发布时间】:2015-12-20 14:16:19
【问题描述】:

我发现我遇到了以下模式分配,我无法让它工作或看起来不错的风格。

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

下面的代码目前没有编译,你建议我怎么做才能使下面的代码遵循这种模式的正确样式?

它无法编译,因为 compr 的内部是返回 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])

【问题讨论】:

    标签: scala playframework future


    【解决方案1】:

    这似乎相当清楚:

    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) 提取到另一个方法或服务。

    【讨论】:

    • 谢谢!多亏了你,我正在慢慢提高我的作曲技巧。
    【解决方案2】:

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

    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
    

    【讨论】:

    • 为什么要这样做?对我来说,您需要先获取它的参考然后在 for-comp 中使用它对我来说没有意义??
    • 我仍然很好奇为什么会这样,但实际上我的第一个电话取决于第二个电话。否则我也可以使用 zip。
    • 那么看来,这是一种理想的行为 :)) 你可以在这里看到“为什么这样做”的答案:stackoverflow.com/questions/34379025
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 2014-11-14
    • 2018-06-26
    • 2011-09-01
    相关资源
    最近更新 更多