Scala 恢复或recoverWith
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36584845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala recover or recoverWith
提问by Henrique Goulart
We are developing some systems in our company in Scala and we have some doubts. We were discussing about how to map the future exceptions and we don't know when we should use the option 1 or the option 2.
我们公司正在用Scala开发一些系统,我们有一些疑问。我们正在讨论如何映射未来的异常,我们不知道什么时候应该使用选项 1 或选项 2。
val created: Future[...] = ???
Option 1:
选项1:
val a = created recover {
case e: database.ADBException =>
logger.error("Failed ...", e)
throw new business.ABusinessException("Failed ...", e)
}
Option 2:
选项 2:
val a = created recoverWith {
case e: database.ADBException =>
logger.error("Failed ...", e)
Future.failed(new business.ABusinessException("Failed ...", e))
}
Could someone explain when should i do the option 1 or the option 2? What is the diff?
有人可以解释我什么时候应该做选项 1 或选项 2 吗?区别是什么?
回答by Aivean
Well, the answer is clearly described in scaladocs:
好吧,scaladocs 中清楚地描述了答案:
/** Creates a new future that will handle any matching throwable that this
* future might contain. If there is no match, or if this future contains
* a valid result then the new future will contain the same.
*
* Example:
*
* {{{
* Future (6 / 0) recover { case e: ArithmeticException => 0 } // result: 0
* Future (6 / 0) recover { case e: NotFoundException => 0 } // result: exception
* Future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3
* }}}
*/
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = {
/** Creates a new future that will handle any matching throwable that this
* future might contain by assigning it a value of another future.
*
* If there is no match, or if this future contains
* a valid result then the new future will contain the same result.
*
* Example:
*
* {{{
* val f = Future { Int.MaxValue }
* Future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue
* }}}
*/
def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U] = {
recoverwraps plain result in Futurefor you (analogue of map), while recoverWithexpects Futureas the result (analogue of flatMap).
recoverFuture为您包装简单的结果(类似于map),而recoverWith期望Future结果(类似于flatMap)。
So, here is rule of thumb:
所以,这是经验法则:
If you recover with something that already returns Future, use recoverWith, otherwise use recover.
如果您使用已经返回的内容进行恢复Future,请使用recoverWith,否则使用recover。
updateIn your case, using recoveris preferred, as it wraps the exception in Futurefor you. Otherwise there is no performance gain or anything, so you just avoid some boilerplate.
更新在您的情况下,使用recover是首选,因为它Future为您包装了异常。否则没有性能提升或任何东西,所以你只需避免一些样板。
回答by Tomer Ben David
Using recoverWithyou are asked to return a wrapped future, using recoveryou are asked to throw an exception.
使用recoverWith你被要求返回一个包装好的未来,使用recover你被要求抛出一个异常。
.recoverWith # => Future.failed(t)
.recover # => throw t
I prefer using recoverWithbecause I think functional programming prefers returning objects than throwing exceptions which is less of a functional style, even if it's internal code block, I think it still holds..
我更喜欢使用,recoverWith因为我认为函数式编程更喜欢返回对象而不是抛出异常,这不是函数式风格,即使它是内部代码块,我认为它仍然适用..
However if I have an internal piece of code in the recovery block which might throw an exception then, in that case, rather than catching it and wrapping it with Future, or Trying it, I might as well just run this piece of code in combination with recoverand it would handle the exception wrapping for you, which would make the code more readable and compact.
但是,如果我在恢复块中有一段内部代码可能会引发异常,那么在这种情况下,与其捕获它并用Future或 Trying it包装它,不如将这段代码与recover它将为您处理异常包装,这将使代码更具可读性和紧凑性。

