Scala 模式:为了产生未来的理解[A]

Scala Pattern: For Comprehension that Yields a Future[A]

Scala中使用什么模式来处理场景:

你有一堆未来(它们可以是任何东西,但为了举例...)

val aF = Future { true }
val bF = Future { Option(3) }
val cF = Future { myObject }

你有一些功能return未来

def fooF: Future[SomeObject]

我想做这样的事情:

for {
    a <- aF
    b <- bF
    c <- cF
} yield {
    if (a) {
        // do stuff with b & c
        fooF
    } else {
        Future.successful(SomeObject)
    }
}

我想 return 一个 Future[SomeObject] 的值,但是我在 yield 语句中调用 fooF,我会得到一个 Future[Future[SomeObject]]

  • 在 Scala 2.12 中 Future 有一个 flatten 方法:

    Creates a new future with one level of nesting flattened, this method is equivalent to flatMap(identity).

    所以你可以写for { ... } yield { ... } flatten.

  • 在 Scala <2.12 中,您可以使用 flatMap(identity) 实现相同的效果(如上所述)


另一种解决方案是使用 flatMap 而不是 for-comprehension:

aF.flatMap { a =>
  if (a) {
    (bF zip cF).flatMap { (b, c) =>
      // do stuff with b & c
      fooF
    }
  } else 
    Future.successful(SomeObject)
  }
}

这是另一个解决方案:

def doStuffWith(a: A, b: B, c: C): Future[SomeObject] = if (a) {
  // do stuff with b & c
  fooF
} else Future.successful(SomeObject)

for {
  a <- aF
  b <- bF
  c <- cF
  d <- doStuffWith(a, b, c)
} yield d

正如@laughedelic 回答中所讨论的,这是一个主观观点,但我相信这种方式更具可读性和可维护性(例如,始终取出函数以对其进行单元测试)。