将scala.util.Try转换为scala.concurrent.Future

时间:2017-09-11 18:07:17

标签: scala future

我开始将Scala 2.11代码库迁移到Scala 2.12。在我的应用程序中,我有一个看起来像这样的方法:

Future {
  someMethodReturningTry()
} onSuccess {
  case Success(result) => processResult()
  case Failure(reason) => log.error(s"Couldn't do it: ${reason.getMessage}")
}

现在,如果你用Scala 2.12编译它,你会得到:

  

方法onSuccess in trait Future已被弃用(自2.12.0起):改为使用foreachonComplete(请记住它们采用的是总计而非部分函数)

所以我开始探索如何以优雅的方式解决这个问题。

someMethodReturningTry()方法确实应返回Try[],因为它涉及解析某些文本结构并且可能会失败,所以我更喜欢保留该方法的返回类型同样的。

我能想到的最好的是

Future {
  someMethodReturningTry()
} flatMap {
  case Success(result) => Future.successful(result)
  case Failure(reason) => Future.failed(reason)
} onComplete {
  case Success(result) => processResult()
  case Failure(reason) => log.error(s"Couldn't do it: ${reason.getMessage}")
}

但这感觉有点多余:创建一个Future只是为了模拟未来某些事物(已经在Future内捕获)的事实进展顺利。

这种方法创造了一个额外的Future我希望摆脱,但我无法弄清楚如何。有什么建议吗?

2 个答案:

答案 0 :(得分:3)

我不清楚为什么你不只是......

Future {
  someMethodReturningTry() match {
    case Success(result) => processResult(result)
    case Failure(reason) => log.error(s"Couldn't do it: ${reason.getMessage}")
  }
}

您可以单独处理或忽略Future失败。

答案 1 :(得分:2)

您可以通过以下方式调整模式匹配:

Future {
  someMethodReturningTry()
} onComplete {
  case Success(Success(result)) => processResult()
  case Success(Failure(reason)) => log.error(s"Couldn't do it: ${reason.getMessage}")
  case Failure(reason) =>
    log.error(s"The future failed: ${reason.getMessage}")
    // or do nothing
}

请注意,仅当onSuccess成功时才会执行Future回调,因此如果Future包含异常,则原始代码不会执行任何操作。如果这是您的意图,您可以将case Failure(reason) =>子句置于空白处(但是如图所示保留错误记录可能更有帮助。)