首页 > 解决方案 > 使用 Cats 从 Future 中提取价值

问题描述

我正在尝试为 GitHub 的 API 编写一个小型库。我正在尝试模拟Github4s 库的行为,这里是这个库的一个例子:

val user1 = Github(accessToken).users.get("rafaparadela")
object ProgramEval {
    val u1 = user1.exec[Eval, HttpResponse[String]]().value
 }

import cats.implicits._
import github4s.GithubResponses.GHResult

ProgramEval.u1 match {
  // Here the actual value of the request is returned, 
  // not the same as Future's onComplete, where the return type is Unit
  case Right(GHResult(result, status, headers)) => result.login
  case Left(e) => e.getMessage
}

我引用文档:

每个 Github4s API 调用都会返回一个 GHIO[GHResponse[A]],它是 Free[Github4s, GHResponse[A]] 的别名。

GHResponse[A] 又是 Either[GHException, GHResult[A]] 的类型别名。

GHResult 包含 Github 给出的结果 A 以及响应的状态码和标头:

在某些时候,他们正在HttpRequest使用HttpClient.scala

我怎么能自己复制这种行为?我曾尝试像示例中那样使用 Cats.Eval,但最终得到了相同的Future[String].

此外,当我提出请求时,我面临一些嵌套问题,例如,要获取一个组织的贡献者列表,我需要做两个HttpRequest

这个结果在 a 上Future[List[Future[Users]]],我面临与上面相同的问题,为了获得结果,我必须这样做:

(result:Future[List[Future[Users]]]) onComplete { users =>
    users.foreach {
        _  onComplete {
            // Process result
        }
    }
}

但我想将值返回为github4s. 我一直在阅读有关Cats 的 Applicative 和 Traversable Functors 的文章,但运气不佳。

标签: scalafuturescala-catsgithub4s

解决方案


您可以转换List[Future]Future[List]使用Future.sequence然后挤压嵌套期货。

结果代码:

val input: Future[List[Future[Users]]] = ???
implicit  val ec: ExecutionContext = ExecutionContext.global
val result: Future[List[Users]] = input.flatMap(list => Future.sequence(list))

推荐阅读