在下面的示例中,我得到异常java.util.NoSuchElementException: Future.filter predicate is not satisfied
我希望检查Future( Test2 )
失败时得到结果if( i == 2 )
。我如何处理过滤/如果在处理组成期货的理解中?
以下是一个适用于Scala REPL的简化示例。
代码:
import scala.concurrent.Future
import scala.util.{ Try, Success, Failure }
import scala.concurrent.ExecutionContext.Implicits.global
val f1 = Future( 1 )
val f2 = for {
i <- f1
if( i == 2 )
} yield "Test1"
f2.recover{ case _ => "Test2" }
f2.value
答案 0 :(得分:29)
在我看来,这是一个更惯用的解决方案。此谓词函数创建包含异常的Future[Unit]
或失败的未来。对于您的示例,这将导致Success("Test1")
或Failure(Exception("Test2"))
。这与“Test1”和“Test2”略有不同,但我发现这种语法更有用。
def predicate(condition: Boolean)(fail: Exception): Future[Unit] =
if (condition) Future( () ) else Future.failed(fail)
你这样使用它:
val f2 = for {
i <- f1
_ <- predicate( i == 2 )(new Exception("Test2"))
j <- f3 // f3 will only run if the predicate is true
} yield "Test1"
答案 1 :(得分:11)
在for-comprehension
中,您按i == 2
进行过滤。由于f1
的值不是两个,因此不会产生Success
,而是产生Failure
。您的错误消息告诉您,过滤器的谓词不满足。但是,f2.recover
会返回新的Future
。 f2
的值未被操纵。它仍然存储Failure
。这就是您在致电f2.value
时收到错误消息的原因。
我能想到的唯一选择是使用else
for-comprehension
,如here所示。
val f2 = for ( i <- f1) yield {
if (i == 2) "Test1"
else "Test2"
}
f2.value
这将Some(Success(Test2))
返回f3.value
。
答案 2 :(得分:8)
当然我自己想出了一个解决方案。也许有更好的,更惯用的解决方案?
import scala.concurrent.Future
import scala.util.{ Try, Success, Failure }
import scala.concurrent.ExecutionContext.Implicits.global
val f1 = Future( 1 )
val f2 = for {
i <- f1
if( i == 2 )
} yield "Test1"
val f3 = f2.recover{ case _ => "Test2" }
// OR val f3 = f2.fallbackTo( Future( "Test2" ) )
f3.value
答案 3 :(得分:0)
我喜欢@pkinsky的想法,并做了一些改进。我放下了创建Exception
对象的代码,如下所示:
val f2 = for {
i <- f1
_ <- shouldTrue( i == 2 )
j <- f3 // f3 will only run if the predicate is true
} yield "Test1"
shouldTrue
函数是使用lihaoyi的sourcecode库实现的:
def shouldTrue(condition: sourcecode.Text[Boolean])(implicit enclosing: sourcecode.Enclosing, file: sourcecode.File, line: sourcecode.Line): Future[Unit] =
if (condition.value) Future.successful( () ) else Future.failed(new Exception(s"${condition.source} returns false\n\tat ${file.value}:${line.value}"))
然后它会自动生成更有意义的异常消息:
java.lang.Exception: i == 2 returns false
at \path\to\example.scala:17