将 Future[T] 转换为 Future[Try[T]]

Transform Future[T] to Future[Try[T]]

我正在尝试理解以下答案 How to carry on executing Future sequence despite failure?。 (希望这不是值得的反对票,因为我正在努力理解这里的代码。)

我不明白 mapValue 如何将 Future[T] 转换为 Future[Try[T]]

def mapValue[T]( f: Future[T] ): Future[Try[T]] = {
  val prom = Promise[Try[T]]()
  f onComplete prom.success
  prom.future
}

f onComplete prom.success 行,它在做什么。我的理解是 prom.success 必须采用 Try[T] 类型的对象,但在这里它没有这样做。也没有对将 Future[T] 转换为 Future[Try[T]] 的 f 赋值。 此外,Future 上的 Then 应该是一个副作用,并且应该 return 与进入其中的相同的未来值,所以不确定转换是如何发生的。

f onComplete prom.success 行被 Scala 编译器解析如下:

  1. 在某些情况下可以省略点和括号,因此 f onComplete x 是一种写法 f.onComplete(x).
  2. 编译器发现 onComplete 方法将函数 f: Try[T] => U 作为参数。您还传递了一个函数作为参数 Promise#success,它具有兼容的签名。

所以该方法正在做的是创建一个 Try[T] 类型的新 Promise(可写未来),并在原始未来完成时用包装 Try[T] 完成该承诺。然后是 returns new Future[Try[T]] promise.

为了扩展 Maxim 的答案,f onComplete prom.success 可以重写为:

f.onComplete(prom.success)

f.onComplete(prom.success(_))

f.onComplete { resultOfFutureAsTry =>
  prom.success(resultOfFutureAsTry)
}

prom.success 设置承诺的 success 值。因此,无论原始 future f 内部发生什么(抛出异常,或者 future 成功完成),新的 future(由 prom.future 返回,并在原始 future 完成后创建)永远是成功的未来。有时成功的未来包含 Failure[T],有时包含 Success[T].

旁注:f.onComplete 通常更像这样使用:

f.onComplete {
  case Success(x) => println(s"Yay, $x worked!")
  case Failure(ex) => println(s"Darn, it failed: $ex")
}

但这只是写函数的一种方便的方式f: Try[T] => U