简体   繁体   English

Scala 未来返回类型

[英]Scala Future return Type

I have the following lines of code...我有以下几行代码...

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

After sometime when I check the value of b, I have the following getting printed.一段时间后,当我检查 b 的值时,我打印了以下内容。

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

Above, b's type is Future[Int];上面,b的类型是Future[Int]; but in the documentation, it says Future's apply method always returns Future(Try[T]).但在文档中,它说 Future 的 apply 方法总是返回 Future(Try[T])。 The documentation and the above example contradict.文档和上面的例子是矛盾的。 Can someone please help.有人可以帮忙吗。

Please post your imports and the documentation you have referenced.请发布您的导入和您引用的文档。

I think best parallel to understanding this is:我认为与理解这一点最相似的是:

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

It can also be helpful to use the Scala REPL for things like this.将 Scala REPL 用于此类事情也很有帮助。 It allows you to easily see types.它使您可以轻松查看类型。

I'm assuming you've done this:我假设你已经这样做了:

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}

Now you have your two lines:现在你有你的两行:

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>)

As you can see the type of b is still of scala.concurrent.Future[Int] as it maps the result of a , an Int , which happens to be 42 , using the function (_: Int -> _ * 2):Int .正如可以看到的类型b是仍然scala.concurrent.Future[Int]作为它映射的结果a ,一个Int ,这恰好是42 ,使用功能(_: Int -> _ * 2):Int

And eventually:最终:

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

From this documentation of Scala Future s :这个 Scala Future s 的文档中

Notice that the 84 you expected is wrapped in a Success , which is further wrapped in a Future .请注意,您期望的 84 包含在Success ,而后者又包含在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 .这是要知道的关键点: Future的值始终是Try类型之一的实例: SuccessFailure Therefore, when working with the result of a future, use the usual Try -handling techniques, or one of the other Future callback methods.因此,在处理 Future 的结果时,请使用通常的Try技术或其他 Future 回调方法之一。

Finally, to extract the Try from the future, either a Success or a Failure , from which we will get our result, or an error:最后,从未来中提取Try ,无论是Success还是Failure ,我们都会从中获得结果或错误:

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

You are mixing two things here.你在这里混合了两件事。 When you create a Future , it is created using the apply function which is in the companion object of Future :当您创建Future ,它是使用Future伴随对象中的 apply 函数创建的:

def apply[T](body: =>T)(implicit @deprecatedName('execctx) executor: ExecutionContext): Future[T] =
    unit.map(_ => body)

So as long as the future is not completed, its type is Future[Int] .所以只要未来没有完成,它的类型就是Future[Int] Once the future completes, the result type will be Future[Try[Int]] .一旦未来完成,结果类型将为Future[Try[Int]]

As stated on onComplete documentation:onComplete文档所述:

When this future is completed, either through an exception, or a value, apply the provided function.当这个未来完成时,通过异常或值,应用提供的函数。

Therefore when you printed the completed future, it already had the Success.因此,当您打印完成的未来时,它已经有了成功。 If you will do the same experiment with a longer wait, and an uncompleted future you will see that its type is not yet success.如果你用更长的等待时间做同样的实验,还有一个未完成的未来,你会看到它的类型还没有成功。

For example, the following code:例如,以下代码:

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)

will output:将输出:

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

You can see that example running here .您可以在此处看到该示例运行。

Let's now look at onComplete .现在让我们看看onComplete The following code:以下代码:

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)

Here we can see an example how to use onComplete when a should complete successfully, and b should throw, and this is exactly what we get.在这里我们可以看到一个例子,当a应该成功完成,而b应该抛出时,如何使用onComplete ,这正是我们得到的。 The output is:输出是:

java.lang.RuntimeException
42

Because the throwingFuture is completed first, it is printed first.因为 throwingFuture 先完成,所以先打印。

The documentation says that a Future[B] contains a Try[B] , which is correct.文档说Future[B]包含Try[B] ,这是正确的。 I think you're getting confused by the toString representation here: Future(Success(84)) is the textual representation of a Future[Int] .我认为您对这里的toString表示感到困惑: Future(Success(84))Future[Int]的文本表示。 For a Future[Try[Int]] , you would have Future(Success(Success(84))) as the textual representation.对于Future[Try[Int]] ,您将Future(Success(Success(84)))作为文本表示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM