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函数的情况下"合并"未来给出的结果.
有任何想法吗?
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)
只需使用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 的回答以获取用于理解的示例