将操作链接到未来期权,然后返回期权?

时间:2018-04-12 22:54:25

标签: scala

我正在编写一个以Option[Credentials]为参数的身份验证客户端。此Credentials对象上有一个.token方法,然后我将使用该方法构造一个HTTP请求以发布到端点。这将返回Future[HttpResponse],然后我需要验证,解组,然后转换回我的返回类型,即Option[String]

我的第一个想法是使用这样的理解:

val resp = for {
  c <- creds
  req <- buildRequest(c.token)
  resp <- Http().singleRequest(req)
} yield resp

然后我发现monad不能像那样组成。我的下一个想法是做这样的事情:

val respFut = Http().singleRequest(buildRequest(token))

    respFut.onComplete {
      case Success(resp) => Some("john.doe")//do stuff
      case Failure(_) => None
    }

不幸的是onComplete会返回一个单元,map会给我留下Future[Option[String]],而我目前知道的剥离未来包装器的唯一方法是使用pipeTo akka框架中的方法。如何将其转换回选项字符串?

3 个答案:

答案 0 :(得分:1)

一旦你获得了Future[T]尝试将其取消包装通常是不错的做法,直到你必须这样做。您可以更改方法以返回Future[Option[String]]吗?您可以在多长时间内处理掉期货?理想情况下它一直都是。

这样的结果会给你一个Future[Option[String]]

val futureResult = creds map {
  case Some(c) => {
    val req = buildRequest(c.token)
    val futureResponse = Http().singleRequest(req)
    futureResponse.map(res => Some(convertResponseToString(res)))
  }
  case None => Future(None)
}

如果确实需要阻止并等待结果,您可以按here.

所述Await.result进行操作

如果你想以更多的monadic风格(在for-comprehension中,就像你尝试过的那样),cats has an OptionT type将有助于此,我认为scalaz也是如此。但是,您是否想要进入这些库中的任何一个都取决于您。

答案 1 :(得分:1)

很容易升级&#34; OptionFuture[Option[...]],因此请使用Future作为主要的monad。并首先处理更简单的案例:

val f: Future[Option[String]] = 
  // no credential? just wrap a `None` in a successful future
  credsOpt.fold(Future.successful(Option.empty[String])) {creds =>
    Http()
      .singleRequest(buildRequest(creds.token))
      .map(convertResponseToString)
      .recover {case _ => Option.empty[String]}
  }

将此未来转变为Option[String]的唯一方法是使用Await.result(...)等待它......但如果未来可以传递给下一个来电者,那就更好了(不阻挡)。

答案 2 :(得分:1)

我不是百分之百确定你的所有类型是什么,但似乎你想要一个混合选项和未来的理解。我经常遇到这种情况,我发现我可以将我的理解作为一种方法来使代码看起来更好一些。

val resp = for {
  c <- creds
  req <- buildRequest(c.token)
} yield for {
  resp <- Http().singleRequest(req)
} yield resp

resp成为一个Option [Future [HttpResponse]],你可以匹配/ partial func around with None意味着代码永远不会执行,因为它的条件失败了。这是一个愚蠢的小技巧,我用它来使理解看起来更好,我希望它能为你的解决方案提供一个暗示。