未使用Await的另一个Future.map中的Future [Future [T]]到Future [T]的未来?

le-*_*ude 3 jvm asynchronous scala scala-2.10

这是一个理论问题.我有一个服务,我可以打电话去做一份工作,但是这项服务可能无法完成所有工作,因此我需要拨打第二个来完成它.

我想知道是否有办法Await.result在map函数中没有结果的情况下执行类似的操作:

val myFirstFuture = asyncRequestA()

myFirstFuture.map(result => {
    result match {
       case isWhatIExpected => result
       case isNot => Await.result(asyncRequestB(), someDuration)
    }
})
Run Code Online (Sandbox Code Playgroud)

我想asyncRequestB()myFirstFuture没有使用Await函数的情况下"合并"未来给出的结果.

有任何想法吗?

Nik*_*kov 6

Future是一个单子.在Scala中使用monad的标准方法是使用"for comprehension":

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

在Scala中,"for comprehension"是一系列和方法应用程序的语法糖flatMap,map并且filter编译器会将这种理解扩展到与Regis的答案相同的内容.

虽然在这种情况下你可能不会完全看到使用"for comprehension"语法带来的好处,但当你进入另一个时Future,当事情变得越来越棘手时,它就会变得光彩照人."理解"基本上做的是它使这三种方法应用程序的嵌套处理变得平坦.

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

myFirstFuture.flatMap{ 
  case r if isWhatIExpected( r ) => Future.succesful( r )
  case r if isNot( r ) => asyncRequestB()
}
Run Code Online (Sandbox Code Playgroud)


Rég*_*les 5

只需使用flatMap而不是map

myFirstFuture.flatMap{ result =>
  result match {
     case isWhatIExpected => Future.successful( result )
     case isNot => asyncRequestB()
  }
}
Run Code Online (Sandbox Code Playgroud)

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

myFirstFuture.flatMap{
   case result: isWhatIExpected => Future.successful( result )
   case _ => asyncRequestB()
}
Run Code Online (Sandbox Code Playgroud)

另请参阅 Nikita Volkov 的回答以获取用于理解的示例