播放框架异步操作:未来恢复无法正常工作

时间:2016-07-24 20:25:49

标签: scala asynchronous playframework future

我在我的Play 2应用程序中有以下代码:

控制器:

...
    def getUserById(id: Long) = Action.async {
        try {
          userService.findById(id)
            .map(u => Ok(Json.toJson(u))
            .recover {
              case e: Exception => Ok("Exception got")
            }
        }
      }
...

服务

...
  override def findAll: Future[Seq[User]] = {
    throw new Exception("Error 1")
  }
...

但是在控制器中我无法捕获服务中抛出的异常(以某种方式忽略了恢复块)。相反,播放带有异常的标准错误页面"错误1"显示。

我做错了什么?

1 个答案:

答案 0 :(得分:5)

您的代码在返回Future之前会抛出异常,因此您应该:

override def findAll: Future[Seq[User]] = Future {
  throw new Exception("Error 1")
}

或只是:

override def findAll: Future[Seq[User]] = 
  Future.failed(new Exception("Error 1"))

以这种方式 - 异常将被包含在Future的实例中,因此每个订阅者都可以异步获取它并按recover进行处理。否则,您必须通过用try{ findAll(...) } catch {...}包装它来同步处理失败。

P.S。抛出异常is not referentially transparent,这就是为什么有时候很难理解这种行为。将错误包含在Future中的方法更加纯粹,因此我更倾向于使代码更清晰。