Ответ 1
Хорошо, ответ четко описан в 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] = {
recover
завершает простой результат в Future
для вас (аналог map
), а recoverWith
ожидает Future
в качестве результата (аналог flatMap
).
Итак, вот эмпирическое правило:
Если вы восстановите что-то, что уже возвращает Future
, используйте recoverWith
, в противном случае используйте recover
.
обн
В вашем случае предпочтительнее использовать recover
, так как recover
перенесет ваше исключение в Future
для вас. В противном случае нет выигрыша в производительности или что-то еще, поэтому вы просто избегаете какого-либо шаблона.