0
votes

I am having an issue in my Play action where my view page requires a ApiResponse object but I am a Future[ApiResponse] and can't seem to "unwrap" the future.

  def confirm(token: String) = Action async { request =>
    // loadTokenInfo returns Future[Option[SP]]
    loadTokenInfo(token).map  { maybeSP =>
      maybeSP match {
        case Some(sp) =>
          val someConfig = SomeConfiguration(..)
          // confirmSubscription returns Future[ApiResponse]
          for {
            apiResp <- apiService.confirmSubscription(sp.account, sp.website, sp.list, sp.listMember)
          } yield Ok(views.html.subscription.confirm(ConfirmPageViewModel(someConfig, sp, apiResp)))

        case _ =>
          Ok(views.html.errorpage.empty(PageNotFound("asdf")))
      }
    }
  }

I am getting the error:

[error] found : scala.concurrent.Future[play.api.mvc.Result] [error] required: play.api.mvc.Result

I tried to map over the apiResp also but that didn't work:

apiResp.map { r =>
  Ok(views.html.subscription.confirm(ConfirmPageViewModel(pageConfig, sp, r)))
}

Do I have to call Await.result here? I don't want to block obviously but not sure what to do at this point.

1

1 Answers

2
votes

I am guessing since you have't specified where the error happens and what confirmSubscription returns--presumably a Future of something.

But I can say that at least you need to return this in your default case:

Future.successful(Ok(views.html.errorpage.empty(PageNotFound("asdf"))))

And for the love of all that is right with the world, don't use Await.result.

Some random, unrelated notes:

  • Using map and getOrElse is more idiomatic than a pattern match on Option.
  • It would be nice if confirmSubscription just took an sp instance and let the apiService decide how it needs to use it.
  • I prefer mapping over Futures rather than using for comprehensions--as you did already--when there is only one.