我有以下元组 - (t1,t2):(尝试,尝试)
我想检查两者是否成功,或者其中一个是否失败,但是避免代码重复。类似的东西:
.then(function success(response) { //do stuff here},
function error(response) {//do stuff here});
当然第二个语句不起作用,因为我需要提供不同的提取变量。但是我必须检查它们,因为我不知道哪个失败并且实际上包含Throwable。 我希望Try会像Future一样行动,所以它会有Try.sequence(t1,t2)。
知道如何优雅地完成这项工作吗?
答案 0 :(得分:6)
您可以将其转换为Try[MyClass]
,如下所示:
val myclass = for {
v1 <- t1
v2 <- t2
} yield new MyClass(v1, v2)
如果t1
失败,或者t1
和t2
都失败,myclass
将是Failure
Exception
t1
}}。如果只有t2
失败,则myclass
将为Failure
Exception
t2
。否则,myclass
将是Success
。然后,您可以使用recover
或其他任何方式正常处理它。
答案 1 :(得分:4)
您可以提取本地方法:
def onFail(e: Throwable) = println(e.getMessage)
(t1,t2) match {
case (Success(v1),Success(v2)) => new MyClass(v1,v2)
case (Failure(e),_) => onFail(e)
case (_,Failure(e)) => onFail(e)
}
我更喜欢OlivierBlanvillain的第一个建议,因为它更容易看到你无法获得无限循环。
答案 2 :(得分:3)
您可以对(_, Failure(e))
案例执行尾递归调用:
@annotation.tailrec
def apply(t1: Try[Any], t2: Try[Any]): Any =
(t1, t2) match {
case (Success(v1), Success(v2)) => new MyClass(v1,v2)
case (Failure(e), _) => println(e.getMessage)
case _ => apply(t2, t1)
}
Cats可让您优雅地完成此任务。对于任何F[_]: Traverse
和G[_]: Applicative
,它定义了Future.sequence
的等效项:
def sequence(fa: F[G[A]]): G[F[A]]
图书馆还提供out of the box instances for Try。进一步阅读traverse documentation。
答案 3 :(得分:2)
为什么不使用Scalactic Or and Every而不是使用Try? 所以你可以写这样的东西
val o1 = Or.from(t1)
val o2 = Or.from(t2)
withGood(o1, o2){(x, y) => {
//do what you want to do if both are good (or Success in Try)
}}.recover{
//do what you want to do if either one is bad (or Failure in Try)
}
PS:我没有加入图书馆。