如何包装Scala进行理解以解决围绕Play的Form折叠的Future?

Joh*_*Doe 0 scala akka playframework playframework-2.2

我有一个处理表单提交的操作.在验证表格之前,我需要解决两个期货.我以为我可以嵌套所有东西,意思是把它fold放在yield理解的块内.

例如:

  def handleFormSubmission = silhouette.SecuredAction.async { implicit request =>
    for {
      user <- userService.findOneByUserId(userId)
      avatar <- avatarService.findOneByUserId(userId)
    } yield {
      myForm.bindFromRequest.fold(
        formWithErrors => formWithErrorsBranch(formWithErrors, user, avatar),
        changeData => changeDataBranch(changeData, user, avatar))
    }
  }
Run Code Online (Sandbox Code Playgroud)

两个分支都返回Future[Result]并且签名folddef fold[R](hasErrors: Form[T] => R, success: T => R): R.据我了解,fold有两个功能与参数Form[T]T与两者的回报R.这意味着如果我在两个分支中返回Future[Result],fold也会返回Future[Result].然而,由于它被包裹内的理解来解决这两个期货useravatar,我就不需要具备Future[Result]而是Result.那是对的吗?如果是这样,我如何以非阻塞方式修复以下编译错误?

type mismatch;
 found   : scala.concurrent.Future[play.api.mvc.Result]
 required: play.api.mvc.Result
Run Code Online (Sandbox Code Playgroud)

Łuk*_*asz 5

如果我理解你的问题,这就是它的解决方法:

  def handleFormSubmission = silhouette.SecuredAction.async { implicit request =>
    for {
      user <- userService.findOneByUserId(userId)
      avatar <- avatarService.findOneByUserId(userId)
      response <- myForm.bindFromRequest.fold(
        formWithErrors => formWithErrorsBranch(formWithErrors, user, avatar),
        changeData => changeDataBranch(changeData, user, avatar)
      )
    } yield response
  }
Run Code Online (Sandbox Code Playgroud)

简单地说,不要这么快就屈服.如果你正在为理解而写作,并且某些东西正在回归未来,请提取值,<-然后将其生成.

<-被翻译成flatMap签名(简化)flatMap(f: A => Future[B]): Future[B].因此,如果您的函数返回未来并且您不想嵌套Future[Future[A]],请使用flatMap.yieldmap签名的,map(f: A => B): Future[B]所以这是为了f不返回a 的情况,Future除非你想要嵌套由于某种原因.如果你的两个分支在表单绑定结果上折叠返回a Future[A]然后你想使用flatMap.

另外,你并没有同时获得用户和头像,而是一个接一个地获得用户和头像.您可能希望先启动计算,然后"等待"两者完成.这可以通过多种方式完成,例如:

val userFuture = userService.findOneByUserId(userId)
val avatarFuture = avatarService.findOneByUserId(userId)
for {
  user <- userFuture
  avatar <- avatarFuture
  response <- ...
} yield response
Run Code Online (Sandbox Code Playgroud)

或者例如 zip

for {
  (user, avatar) <- userService.findOneByUserId(userId) zip avatarService.findOneByUserId(userId)
  response <- ...
} yield response
Run Code Online (Sandbox Code Playgroud)