scala – 以功能方式进行多个API调用
通过使用
Scala和Cats(或者可能是另一个专注于类别理论和/或函数式编程的库),以最具功能性(代数)的方式解决这个问题的最佳方法是什么?
资源 如果我们有以下方法执行REST API调用来检索单个信息? type FutureApiCallResult[A] = Future[Either[String,Option[A]]] def getNameApiCall(id: Int): FutureApiCallResult[String] def getAgeApiCall(id: Int): FutureApiCallResult[Int] def getEmailApiCall(id: Int): FutureApiCallResult[String] 如您所见,它们会产生异步结果. Either monad用于在API调用期间返回可能的错误,而Option用于在API未找到资源时返回None(这种情况不是错误,而是可能的和期望的结果类型). 以功能方式实现的方法 case class Person(name: String,age: Int,email: String) def getPerson(id: Int): Future[Option[Person]] = ??? 如果任何API调用失败或任何API调用返回None(整个Person实体无法组合),则此方法应使用上面定义的三个API调用方法异步组合并返回Person或None. 要求 出于性能原因,所有API调用必须以并行方式完成 我猜 我认为最好的选择是使用Cats Semigroupal Validated但是在尝试处理Future和如此多的嵌套Monads时我迷路了:S 任何人都可以告诉我你将如何实现这一点(即使改变方法签名或主要概念)或指向我正确的资源?我在编码时对Cats和Algebra很新,但我想学习如何处理这种情况,以便我可以在工作中使用它. 解决方法
您可以使用cats.Parallel类型类.这使得一些非常整洁的组合器具有EitherT,当并行运行时会累积误差.因此,最简单,最简洁的解决方案是:
type FutureResult[A] = EitherT[Future,NonEmptyList[String],Option[A]] def getPerson(id: Int): FutureResult[Person] = (getNameApiCall(id),getAgeApiCall(id),getEmailApiCall(id)) .parMapN((name,age,email) => (name,email).mapN(Person)) 有关Parallel的更多信息,请访问cats documentation. 编辑:这是没有内部选项的另一种方式: type FutureResult[A] = EitherT[Future,A] def getPerson(id: Int): FutureResult[Person] = (getNameApiCall(id),getEmailApiCall(id)) .parMapN(Person) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |