6

I am slightly confused when to use which because futures are allowed to fail. If futures are allowed to fail, then to me, that sounds like a Try[] in itself.

And if the Try[] is wrapped inside a Future, then what is the difference with a regular Future[]?

user1555300
  • 185
  • 1
  • 7

2 Answers2

10

There's really no reason to ever use a Future[Try[T]]. You add no benefit over a plain Future, and a good deal of complexity. Trys are sort of the synchronous version of Futures. You use them to wrap operations you are blocking on that might fail, or potentially-failing operations that are lazily evaluated. Futures are for when you need asynchronous semantics as well.

Karl Bielefeldt
  • 147,435
  • 4
    That's not entirely true. The semantics isn't the same. If you use a plain Future, you can use the recoverWith method to handle a possible error of a Future execution. But Future[Try[T]] make it more obvious for the caller to handle errors returning from the async execution. – Tomer Sela Feb 25 '18 at 22:45
  • 1
    A function that returns Future[Try[T]] tells me there's a possible failure there that I have to handle. A Future[T] tells me much less, so I have to either write a recover for all Futures I encounter, or look into the function code to see if a failure is actually expected. Sure, a Future always has the potential to fail, but some functions expect failures and others don't and I don't like hiding that information. – Tim Gautier Jan 25 '19 at 17:09
0

As Karl already answered, in your case there is no reason to use Future[Try[T]], though in some cases Future[Try[T]] might be useful.

Example: when you need to do multiple requests but if some of them fails you still want to keep other results

Here when one request fails, you dont get any results:

val requests = dataList.map(requestToBackend)
//collect all results with sequence
val results = Future.sequence(requests)

Other solution is to recover with try and then collect only successful results

val requests = dataList.map{ data =>
  requestToBackend(data)
    .map(Success)
    .recover { case x => Failure(x) }
}
//collect all results with sequence
val results = Future.sequence(requests).collect{ case Success(value) => value }