scala - 当容器项是 Either 时如何组合期货
问题描述
当我的返回值 whereEither[String, User]
和Either[String, Seq[Sale]]
.
我的函数实际上返回期货,所以一旦我将它们包装在期货中,我就会面临问题。
当内部容器为 Either 类型时,我需要有关如何组合 Futures 的帮助。
注意:我将不得不对销售集合执行进一步的业务逻辑,但到目前为止我需要的总体大纲如下:
import scala.concurrent._
import ExecutionContext.Implicits.global
case class User(id: Int)
case class Sale(id: Int)
case class Response(user: User, sales: Seq[Sale])
def getUser(id: Int): Future[Either[String, User]] = Future(Right(User(123)))
def getSales(userId: Int): Future[Either[String, Seq[Sale]]] = Future(Right(Seq(Sale(1), Sale(2))))
val response = for {
user <- getUser(123)
sales <- getSales(user.id)
} yield Response(user, sales)
println(response)
我在 playframework 操作方法中执行此操作:
def getUser(id: Int) = Action.async {
val response = for {
user <- getUser(123)
sales <- getSales(user.id)
} yield Response(user, sales)
Ok(response) // gets converted to JSON
}
解决方案
如果你不能使用猫,那么你必须自己实现变压器。这是一个示例Either[String,_]
:(链接到 Scastie)
import scala.concurrent._
import ExecutionContext.Implicits.global
case class FutureEither[A](value: Future[Either[String,A]]){
def map[B](f: A => B)(implicit ec: ExecutionContext): FutureEither[B] = FutureEither(value.map(_.map(f)))
def flatMap[B](f: A => FutureEither[B])(implicit ec: ExecutionContext): FutureEither[B] = FutureEither(value.flatMap{
case Left(s) => Future.successful(Left(s))
case Right(a) => f(a).value
})
}
case class User(id: Int)
case class Sale(id: Int)
case class Response(user: User, sales: Seq[Sale])
def getUser(id: Int): Future[Either[String, User]] = Future(Right(User(123)))
def getSales(userId: Int): Future[Either[String, Seq[Sale]]] = Future(Right(Seq(Sale(1), Sale(2))))
val response = for {
user <- FutureEither(getUser(123))
sales <- FutureEither(getSales(user.id))
} yield Response(user, sales)
println(response.value.onComplete(println(_)))
请注意,您可以轻松地对 wrapping 进行抽象Future[_]
。它只需要是一个单子(需要有map
和flatMap
和apply
方法)。如果你这样做,并添加更多的语法细节,你最终会得到EitherT
from cat 。
推荐阅读
- apache-spark - 使用 databricks-connect 从 pycharm 调用 spark_udf 时的 MLflow FileNotFound
- android - 我如何在 Firestore 中使用 DocumentRecerence?
- css - 新的 Google Chrome:复制 CSS 时如何避免不需要的换行符?
- amazon-s3 - 如何使用 sudo mount_nfs -o vers=3,nolock -v 将 aws-s3 映射为 MAC 上的本地驱动器
- mysql - mysql 在同一列上有多个条件
- macos - 在 macOS 上获取与特定文件关联的应用程序
- c++ - 为什么创建动态 .dll 文件时会有一个 .lib 文件?
- python - 显示图例 pandas 绘制多个 Y 轴
- database - TDengine 时间戳数据超出范围
- javascript - object-fit 改变图像的宽度,但不改变元素。如何在 JS 中获取图像的宽度?