3

这是一个理论问题。我有一个服务可以调用来完成工作,但该服务可能无法完成所有工作,因此我需要调用第二个服务来完成它。

Await.result我想知道是否有一种方法可以在 map 函数中没有结果的情况下做类似的事情:

val myFirstFuture = asyncRequestA()

myFirstFuture.map(result => {
    result match {
       case isWhatIExpected => result
       case isNot => Await.result(asyncRequestB(), someDuration)
    }
})

我想在不使用 Await 函数来获得结果的情况下“合并”由asyncRequestB()into给出的未来。myFirstFuture

有任何想法吗?

4

2 回答 2

6

Future是一个单子。在 Scala 中使用 monad 的标准方法是使用“理解”:

for {
  firstResult <- firstFuture
  secondResult <- firstResult match {
    case isWhatIExpected => Future.successful( firstResult )
    case isNot => asyncRequestB()
  }
}
yield secondResult

在 Scala 中,“用于理解”是一系列flatMap,mapfilter方法应用程序的语法糖,在引擎盖下,编译器会将这种理解扩展为与 Regis 的答案相同的东西。

尽管在这种情况下,您可能无法完全看到使用“for comprehension”语法的好处,但当您插入另一个语法Future并且事情开始变得棘手时,它就会大放异彩。“用于理解”基本上所做的是将这三个方法应用程序的其他多层嵌套扁平化。

其次,还有一种方法可以通过使用“部分函数”在语法上优化 Regis 的解决方案:

myFirstFuture.flatMap{ 
  case r if isWhatIExpected( r ) => Future.succesful( r )
  case r if isNot( r ) => asyncRequestB()
}
于 2013-05-29T10:10:46.743 回答
5

只需使用flatMap而不是map

myFirstFuture.flatMap{ result =>
  result match {
     case isWhatIExpected => Future.successful( result )
     case isNot => asyncRequestB()
  }
}

作为旁注,您甚至可以像这样缩短它:

myFirstFuture.flatMap{
   case result: isWhatIExpected => Future.successful( result )
   case _ => asyncRequestB()
}

另请参阅 Nikita Volkov 的回答,了解使用 for comprehensions 的示例

于 2013-05-29T09:16:41.720 回答