首页 > 解决方案 > 链接多个任意一个

问题描述

考虑场景

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 语句。

有没有更好的方法来做到这一点?

标签: scalaeither

解决方案


所以你有一个Listof Future Eithers。

val lfe :List[Future[Either[String,Unit]]] = ???

要将所有Left字符串合二为一,Future[String]您可以这样做...

val res :Future[String] =
  Future.sequence(lfe)
        .map(_.flatMap(_.fold(Some(_),_ => None)).mkString(" & "))

推荐阅读