Dealing with failed futures

2019-04-10 04:38发布

问题:

In Play Framework 2.3, an action can produce a result from a successful future call like this:

def index = Action.async {
  val futureInt = scala.concurrent.Future { intensiveComputation() }
  futureInt.map(i => Ok("Got result: " + i))
}

But how can an action deal with a failed future call, i.e., a future that was completed by calling failure() instead of success()?

For instance, how could an action produce a InternalServerError result with the message returned in the future's failure's throwable?

onComplete and onFailure callbacks don't seem to fit the action's flow (it needs to return a result, either from a successful future or a failed one).

回答1:

For a single Action, you can do this with recover, recovering the failed Future to a Result:

def index = Action.async {
    val futureInt = scala.concurrent.Future { intensiveComputation() }
    futureInt.map(i => Ok("Got result: " + i))
        .recover{ case e: Exception => InternalServerError(e.getMessage) }
}

recover in this case is a PartialFunction[Throwable, Result], so you can be more fine grained with your error handling, and anything that is not defined in the PartialFunction will remain a failed Future. More generally, you could probably use a custom defined Action that implements this.