如果 f 和 g 都失败了,你怎么能让 `first` return 成为 `Failure`?
How can you make `first` return a `Failure` if both f and g fail?
来自官方scala的例子documentation:
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = promise[T]
f onSuccess {
case x => p.trySuccess(x)
}
g onSuccess {
case x => p.trySuccess(x)
}
p.future
}
Note that in this implementation, if neither f nor g succeeds, then
first(f, g) never completes (either with a value or with an
exception).
有warning,但是没有对应的解决方法。如果 f 和 g 都失败了,你如何让 first
return 变成 Failure
?
像这样的东西可以完成这项工作,虽然它不是基于与您的示例相同的逻辑(这个解决方案是 错误的 ,请检查 Update)
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = Promise[T]
p.completeWith(f.fallbackTo(g))
p.future
}
如果两者都失败,first
holds throwable 来自 f
。
更新(基于@Jatin 的评论):
我的第一个解决方案是错误的,因为如果 f
未来永远不会完成,那么即使 g
完成,first
也永远不会完成。此更新的解决方案使用第一个完成的值非确定性地完成 Promise
:
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = Promise[T]
p.completeWith(Future.firstCompletedOf(Seq(f.fallbackTo(g),g.fallbackTo(f))))
p.future
}
另一个解决方案:您需要在列表中找到第一个成功的。或者如果全部失败则失败。
该解决方案本质上有点有效,很高兴看到纯函数式实现:
def second[T](ls: Seq[Future[T]]): Future[T] = {
val p = Promise[T]()
val size = ls.size
val count = new AtomicInteger(0)
ls.foreach(x => x onComplete{
case Success(a) => p.tryCompleteWith(x)
case Failure(y) => if(count.incrementAndGet() == size) p.tryCompleteWith(x)
})
p.future
}
下面按预期打印 2
:
second(List(Future{ Thread.sleep(5000); 1}, Future{Thread.sleep(3000) ;2}, Future{throw new RuntimeException})) onComplete{
case Success(x) => println(x)
case Failure(y) => y.printStackTrace()
}
来自官方scala的例子documentation:
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = promise[T]
f onSuccess {
case x => p.trySuccess(x)
}
g onSuccess {
case x => p.trySuccess(x)
}
p.future
}
Note that in this implementation, if neither f nor g succeeds, then first(f, g) never completes (either with a value or with an exception).
有warning,但是没有对应的解决方法。如果 f 和 g 都失败了,你如何让 first
return 变成 Failure
?
像这样的东西可以完成这项工作,虽然它不是基于与您的示例相同的逻辑(这个解决方案是 错误的 ,请检查 Update)
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = Promise[T]
p.completeWith(f.fallbackTo(g))
p.future
}
如果两者都失败,first
holds throwable 来自 f
。
更新(基于@Jatin 的评论):
我的第一个解决方案是错误的,因为如果 f
未来永远不会完成,那么即使 g
完成,first
也永远不会完成。此更新的解决方案使用第一个完成的值非确定性地完成 Promise
:
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = Promise[T]
p.completeWith(Future.firstCompletedOf(Seq(f.fallbackTo(g),g.fallbackTo(f))))
p.future
}
另一个解决方案:您需要在列表中找到第一个成功的。或者如果全部失败则失败。
该解决方案本质上有点有效,很高兴看到纯函数式实现:
def second[T](ls: Seq[Future[T]]): Future[T] = {
val p = Promise[T]()
val size = ls.size
val count = new AtomicInteger(0)
ls.foreach(x => x onComplete{
case Success(a) => p.tryCompleteWith(x)
case Failure(y) => if(count.incrementAndGet() == size) p.tryCompleteWith(x)
})
p.future
}
下面按预期打印 2
:
second(List(Future{ Thread.sleep(5000); 1}, Future{Thread.sleep(3000) ;2}, Future{throw new RuntimeException})) onComplete{
case Success(x) => println(x)
case Failure(y) => y.printStackTrace()
}