scala - 链接多个任意一个
问题描述
考虑场景
trait Checker {
def check()(implicit ec: ExecutionContext): Future[Either[String, Unit]]
}
该特征由各种类实现。
让我们说
class CheckerImpl1 extends Checker {
override def check()(implicit ec: ExecutionContext): Future[Either[String, Unit]] = ???
}
class CheckerImpl2 extends Checker {
override def check()(implicit ec: ExecutionContext): Future[Either[String, Unit]] = ???
}
现在,我需要定义一个新函数,它将check()
按顺序为每个实现类调用函数(顺序无关紧要)并返回一个新的或者,即Future[Either[String, Unit]]
这里的 String 是实现结果的连接left
字符串check()
。
因此,如果CheckerImpl1.check()
返回Left("error1")
并CheckerImpl2.check()
返回Left("error2")
,则新函数的结果将返回Left("error1&error2")
(& 只是分隔两个字符串)。
或者
因此,如果CheckerImpl1.check()
返回Right(())
并CheckerImpl2.check()
返回Left("error2")
,则新函数的结果将返回Left("error2")
。
或者
因此,如果CheckerImpl1.check()
返回Right(())
并CheckerImpl2.check()
返回Right(())
,则新函数的结果将返回Right(())
。
我现在所做的是
(CheckerImpl1.check(), CheckerImpl2.check())
.mapN {
case (Right(_), Right(_)) => Right(())
case (Left(err), Right(_)) => Left(err)
case (Right(_), Left(err)) => Left(err)
case (Left(err1), Left(err2)) => Left(err1 ++ "&" ++ err2)))
}
但这不是一个理想的解决方案,因为如果我添加更多的实现,那么我需要添加更多的这些 case 语句。
有没有更好的方法来做到这一点?
解决方案
所以你有一个List
of Future
Either
s。
val lfe :List[Future[Either[String,Unit]]] = ???
要将所有Left
字符串合二为一,Future[String]
您可以这样做...
val res :Future[String] =
Future.sequence(lfe)
.map(_.flatMap(_.fold(Some(_),_ => None)).mkString(" & "))