我如何获得这种理解才能返回?

时间:2019-01-20 01:13:12

标签: scala playframework future for-comprehension

我正在创建与服务对话的控制器。控制器(基于播放库AbstractController)接收隐式请求并返回Future[Result]。服务接收请求并返回Future[Model]。我有一些要防范模型创建的条件。例如,如果用户没有访问权限,则不应创建任何模型。

 def create(): Action[JsValue] = Action(parse.tolerantJson).async { implicit request: Request[JsValue] =>
    val modelOpt: Option[Future[Result]] =  // I've tried Future[Result] here too
      for {
        attributes <- (request.body \ "data" \ "attributes").validate[JsObject].asOpt
        userOpt = (request.body \ "data" \ "attributes" \ "user-name").validate[String].asOpt
        user <- userOpt
        model <- service1.createModel(user) // Create Model returns type of Future[Model], so this should flatMap to Model
      } yield {
        val permission = checkPermission(user)  // Returns true or false, depending on if the user is permissioned
        (userOpt, permission) match {
          case (Some(_), true) => Ok(model)
          case (Some(_), false) => Forbidden
          case (None, _) => NotFound 
          case (_, false) => Forbidden 
        }
      }

    modelOpt.getOrElse(Future { InternalServerError })
  }

但是,编译器抱怨说它期望Option[Future[Result]]并且收到了Future[Result](可能是由于我为modelOpt提供的类型)。但是,我认为如果Json无法验证,它将给我None,因此我认为外部类型确实必须是一个Option。谁能告诉我发生了什么事?

1 个答案:

答案 0 :(得分:1)

如果您查看特征Option[A]中方法getOrElse的签名:

final def getOrElse[B >: A](default: => B): B

它会解开Option以返回A或它的超类型,直到B

现在,在modelOpt为Option[Future[Result]]的情况下,将getOrElse应用于给定类型为Future[Result](或其子类型)的默认值将导致Future[Result]

类似于getOrElse的工作方式,但将Option保留在原位,方法orElse具有以下签名:

final def orElse[B >: A](alternative: => Option[B]): Option[B]

因此,将orElse应用于modelOpt如下所示,将返回所需的Option[Future[Result]]

modelOpt.orElse(Some(Future.successful(InternalServerError)))

请注意,Future.successful用于提供具有指定结果的已经完成的Future。