如何根据Future的结果返回不同的响应?

时间:2015-12-23 11:33:09

标签: scala spray akka-http

我的登录端点大致与此类似

get {
  (path("token") & parameters("email", "password")) { (email, password) =>
    complete {
      DBManager.getUserByEmail(email) match {
        case Some(user) =>
          // Check everything is return something
          UserWire(user)
        case None => StatusCodes.NotFound -> "User doesn't exist"
      }
    }
  }
}

DBManager.getUserByEmail返回Option[User]。我刚刚切换到Slick,其中所有内容都是异步的,因此方法现在返回Future[User]

如果未来失败,我该如何发送所需的回复?我试过这个

    complete {
      DBManager.getUserByEmail(email).map(user => {
        // Check everything is return something
        UserWire(user)
      }).recoverWith { case ex => Future.successful(StatusCodes.NotFound -> "User doesn't exist") }
    }

无法使用

进行编译
Error:(497, 26) type mismatch;
 found   : scala.concurrent.Future[Product with Serializable]
 required: akka.http.scaladsl.marshalling.ToResponseMarshallable
          }).recoverWith { case ex => Future.successful(StatusCodes.NotFound -> "User doesn't exist") }
                         ^

我该如何解决?

2 个答案:

答案 0 :(得分:4)

在喷涂中你可以使用onComplete,它会得到一个未来并返回一个指令,所以在你的情况下:

onComplete(DBManager.getUserByEmail(email)) {
  case Success(optUser) =>
    complete {optUser.map(UserWire(_)).getOrElse(StatusCodes.NotFound -> "User doesn't exist") }
  case Failure(_) =>
    complete { InternalServerError() }
}

虽然我从未使用过,但似乎Akka http有same method

答案 1 :(得分:1)

第一件事。在构建反应式应用程序时,最好只在成功的操作上运行。处理未来失败需要比成功运营更多的资源。 let long_circuit_or = (||);; let print_true x = print_string x; true;; (* just prints "4" *) print_true "4" || print "5";; (* prints "45" *) long_circuit_or (print_true "4") (print_true "5");; 的反复版本应返回DBManager.getUserByEmail

当你将未来的地图结果带到Marshallable表格或回复时。

Future[Option[User]]