Scala 未来 return 类型

Scala Future return Type

我有以下几行代码...

val a = Future { Thread.sleep(10*1000); 42 }
val b = a.map(_ * 2)

一段时间后,当我检查 b 的值时,我打印了以下内容。

scala.concurrent.Future[Int] = Future(Success(84))

如上,b的类型是Future[Int];但在文档中,它说 Future 的应用方法总是 returns Future(Try[T])。文档和上面的例子相矛盾。有人可以帮忙吗

文档说 Future[B] 包含 Try[B],这是正确的。我认为您对此处的 toString 表示感到困惑:Future(Success(84))Future[Int] 的文本表示。对于 Future[Try[Int]],您将使用 Future(Success(Success(84))) 作为文本表示。

你在这里混合了两种东西。当您创建 Future 时,它是使用 companion object of Future:

中的应用函数创建的
def apply[T](body: =>T)(implicit @deprecatedName('execctx) executor: ExecutionContext): Future[T] =
    unit.map(_ => body)

所以只要future没有完成,它的类型就是Future[Int]。 Future 完成后,结果类型将为 Future[Try[Int]].

onComplete 文档所述:

When this future is completed, either through an exception, or a value, apply the provided function.

因此当你打印完成的未来时,它已经成功了。如果您将等待更长的时间和未完成的未来进行相同的实验,您会发现它的类型尚未成功。

例如下面的代码:

implicit val ec = scala.concurrent.ExecutionContext.global
val a = Future { Thread.sleep(10*1000); 42 }
println(a)
Await.result(a, Integer.MAX_VALUE.seconds)
println(a)

将输出:

Future(<not completed>)
Future(Success(42))

你可以看到那个例子 运行 here.

现在让我们看看onComplete。以下代码:

val a = Future { Thread.sleep(10*1000); 42 }
a.onComplete {
  case Success(value) =>
    println(value)
  case Failure(exception) =>
    println(exception)
}

val b = Future { throw new RuntimeException }
b.onComplete {
  case Success(value) =>
    println(value)
  case Failure(exception) =>
    println(exception)
}

Await.result(a, Integer.MAX_VALUE.seconds)
Await.result(b, Integer.MAX_VALUE.seconds)

这里我们可以看到一个例子,当 a 应该成功完成,b 应该抛出错误时,如何使用 onComplete,这正是我们得到的结果。输出为:

java.lang.RuntimeException
42

因为throwingFuture先完成,所以先打印。

请post你的导入和你引用的文档。

我认为与理解这一点最相似的是:

Try[T] 就像 Option[T]Try[T] 总是 Success[T](value: T)Failure[T](exception: Throwable),就像 Option[T] 总是 Some[T](value: T)None

对于这样的事情,使用 Scala REPL 也很有帮助。它可以让您轻松查看类型。

我假设你已经这样做了:

scala> import scala.concurrent.Future
import scala.concurrent.Future

scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global

scala> import scala.util.{Failure, Success}
import scala.util.{Failure, Success}

现在你有两条线:

scala> val a = Future { Thread.sleep(10*1000); 42 }
val a: scala.concurrent.Future[Int] = Future(<not completed>)

scala> val b = a.map(_ * 2)
val b: scala.concurrent.Future[Int] = Future(<not completed>)

如您所见,b 的类型仍然是 scala.concurrent.Future[Int],因为它映射了 a 的结果,一个 Int,恰好是 42, 使用函数 (_: Int -> _ * 2):Int.

最终:

scala> b
val res0: scala.concurrent.Future[Int] = Future(Success(84))

来自 this documentation of Scala Futures:

Notice that the 84 you expected is wrapped in a Success, which is further wrapped in a Future. This is a key point to know: The value in a Future is always an instance of one of the Try types: Success or Failure. Therefore, when working with the result of a future, use the usual Try-handling techniques, or one of the other Future callback methods.

最后,要从未来提取 TrySuccessFailure,我们将从中得到结果,或错误:

scala> b.onComplete {
     |     case Success(value) => println(s"Got the callback, value = $value")
     |     case Failure(e) => e.printStackTrace
     | }
Got the callback, value = 84