【问题标题】:How to best handle Future.filter predicate is not satisfied type errors如何最好地处理 Future.filter 谓词不满足类型错误
【发布时间】:2016-01-03 02:22:02
【问题描述】:

我喜欢 scala 的类型安全性,但我一直遇到的一个运行时错误是

 Future.filter predicate is not satisfied

我知道为什么会收到此错误,只是在寻找有关如何最好地解决此错误并优雅地处理它的建议,或者我做错了?

val r: Future[play.api.mvc.Result] = for {
  account <- accountServer.get(...)
  if account.isConfirmed
  orders <- orderService.get(account, ...)
} yield {
  ...
}

如果账号没有被确认,就会出现上述错误。

我会认为,由于过滤器有可能失败,因此 scala 会将收益率返回值设为选项。没有?

【问题讨论】:

  • 如果将结果类型声明为Result,它如何返回选项?
  • recover Future 会产生有意义的错误。 r 不应该是 Future[Result] 吗?
  • @m-z 是的,我把它改成了未来,谢谢。

标签: scala playframework future


【解决方案1】:

filterFuture 没有意义,因为类型系统不知道为else 情况返回什么,因此依赖它是不安全的(通过使用 if-guard)。但是您可以在理解范围内执行此操作以实现相同的目的:

val r: Future[play.api.mvc.Result] = for {
  account <- accountServer.get(...)
  orders <- if (account.isConfirmed) orderService.get(account, ...) 
            else Future.successful(Seq.empty) 
} yield {
  ...
}

(正如 Jean Logeart 的回答,但在理解范围内)

【讨论】:

  • 如何有条件地将成功的accountServer.get 转换为失败?这种方法有什么潜在的缺点吗?
【解决方案2】:

您可能想使用一个简单的flatMap,您可以在其中指定else 大小写:

val orders = accountServer.get(...)
                          .flatMap { account => 
                            if(account.isConfirmed) orderService.get(account, ...)
                            else Future.successful(Seq.empty)
                          }

【讨论】:

  • 但我想在 for-comp 中处理这个问题,因为我目前正在使用它们分配。还是根本不可能?
【解决方案3】:

for-comprehension is just syntax sugar代表foreachmapflatMapfilter等链。当你写if account.isConfirmed时,这相当于使用Future的filter方法。

已解决的 Future 的值包含在 Try 中,它可以采用 Success 或 Failure 的形式。 (将此与 Option 比较,它可以采用 Some 或 None 的形式。)

很像 Option 的 filter 将 Some 转换为 None 如果包含的值未通过谓词,Future/Try filter 方法会将 Success 转换为 Failure。如果您查看 Future.filterTry.filter 的实现,这是通过返回带有 new NoSuchElementException 的失败来完成的,其中包含您提到的 predicate is not satisfied 消息。

因此,错误消息本身完全是设计使然,并且与类型系统一致。 for-comprehension 中的任何步骤都只会投射另一个 Future,因此编写 if account.isConfirmed 将投射成功,如果它通过过滤器,或者如果没有,则投射失败。

这就是为什么当您使用if/filter 时 Scala 不会将 Future[Result] 更改为 Future[Option[Result]] 的答案。如果您希望生成包含 Option 或空 Seq 的成功 Future,则必须明确地这样做(如 Jean Logeart'sAlvaro Carrasco's 答案中所示)。

【讨论】:

    猜你喜欢
    • 2020-06-18
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 2012-05-14
    • 1970-01-01
    相关资源
    最近更新 更多