54

我是 scala 期货的新手,我对 scala 期货的回报值有疑问。

因此,通常 Scala 未来的语法是

 def downloadPage(url: URL) = Future[List[Int]] {

 }

我想知道如何List[Int]从调用此方法的其他方法访问 。

换句话说,

val result = downloadPage("localhost") 

那么摆脱未来的方法应该是什么List[Int]

我尝试过使用 map 方法,但无法成功。`

4

6 回答 6

30

Success(listInt) => 我想返回 listInt 的情况,但我不知道该怎么做。

最佳做法是您返回该值。相反,您只需将未来(或用 , 等转换的版本mapflatMap传递给需要此值的每个人,他们可以添加自己的onComplete.

如果您确实需要返回它(例如,在实现旧方法时),那么您唯一能做的就是阻止(例如 with Await.result)并且您需要决定等待多长时间。

于 2013-07-18T06:05:49.060 回答
15

You need to wait for the future to complete to get the result given some timespan, here's something that would work:

  import scala.concurrent.duration._

  def downloadPage(url: URL) = Future[List[Int]] {
    List(1,2,3)
  }

  val result = downloadPage("localhost")

  val myListInt = result.result(10 seconds)

Ideally, if you're using a Future, you don't want to block the executing thread, so you would move your logic that deals with the result of your Future into the onComplete method, something like this:

  result.onComplete({
    case Success(listInt) => {
      //Do something with my list
    }
    case Failure(exception) => {
      //Do something with my error
    }
  })
于 2013-07-18T02:51:42.177 回答
8

我希望你已经解决了这个问题,因为它在 2013 年被问到,但也许我的回答可以帮助其他人:

如果您使用的是 Play Framework,它支持异步 Actions(实际上所有 Actions 内部都是异步的)。创建异步操作的一种简单方法是使用Action.async(). 您需要Future[Result]为此功能提供一个。

现在您可以使用 Scala 的 map、flatMap、for-comprehension 或 async/await 进行Future[List[Int]]转换Future[Result]。这是 Play Framework 文档中的示例。

import play.api.libs.concurrent.Execution.Implicits.defaultContext

def index = Action.async {
  val futureInt = scala.concurrent.Future { intensiveComputation() }
  futureInt.map(i => Ok("Got result: " + i))
}
于 2015-05-09T21:20:06.873 回答
8

你可以做这样的事情。如果方法中给出的等待时间Await.result小于awaitable执行所需的时间,您将有一个TimeoutException,并且您需要处理错误(或任何其他错误)。

import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{Try, Success, Failure}
import scala.concurrent.duration._

object MyObject {
    def main(args: Array[String]) {

        val myVal: Future[String] = Future { silly() }

        // values less than 5 seconds will go to 
        // Failure case, because silly() will not be done yet
        Try(Await.result(myVal, 10 seconds)) match {
            case Success(extractedVal) => { println("Success Happened: " + extractedVal) }
            case Failure(_) => { println("Failure Happened") }
            case _ => { println("Very Strange") }
        }      
    }

    def silly(): String = {
        Thread.sleep(5000)
        "Hello from silly"
        }
}
于 2017-03-10T02:15:13.390 回答
3

我发现思考未来的最佳方式是一个盒子,它会在某个时候包含你想要的东西。未来的关键是你永远不会打开盒子。试图强行打开盒子会导致你阻塞和悲伤。相反,您将 Future 放在另一个更大的盒子中,通常使用 map 方法。

这是一个包含字符串的 Future 示例。当 Future 完成时,将调用 Console.println:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object Main {

  def main(args:Array[String]) : Unit = {
    val stringFuture: Future[String] = Future.successful("hello world!")
    stringFuture.map {
      someString =>
        // if you use .foreach you avoid creating an extra Future, but we are proving
        // the concept here...
        Console.println(someString)
    }
  }
}

请注意,在这种情况下,我们正在调用 main 方法,然后……完成。由全局 ExecutionContext 提供的字符串的 Future 完成调用 Console.println 的工作。这很棒,因为当我们放弃控制 someString 何时出现以及何时调用 Console.println 时,我们让系统自行管理。相反,看看当我们试图强制打开盒子时会发生什么:

val stringFuture: Future[String] = Future.successful("hello world!")
val someString = Future.await(stringFuture)

在这种情况下,我们必须等待——让一个线程不停地旋转它的拇指——直到我们得到 someString。我们已经打开了盒子,但我们必须征用系统的资源才能拿到它。

于 2015-11-20T19:21:01.507 回答
1

还没有提到,所以我想强调一下使用Futurewith for-comprehension 以及顺序执行和并行执行的区别。

例如,对于顺序执行:

object FuturesSequential extends App {

  def job(n: Int) = Future {
    Thread.sleep(1000)
    println(s"Job $n")
  }

  val f = for {
    f1 <- job(1)
    f2 <- job(2)
    f3 <- job(3)
    f4 <- job(4)
    f5 <- job(5)
  } yield List(f1, f2, f3, f4, f5)
  f.map(res => println(s"Done. ${res.size} jobs run"))
  Thread.sleep(6000) // We need to prevent main thread from quitting too early
}

对于并行执行(请注意,在Future理解之前):

object FuturesParallel extends App {

  def job(n: Int) = Future {
    Thread.sleep(1000)
    println(s"Job $n")
  }

  val j1 = job(1)
  val j2 = job(2)
  val j3 = job(3)
  val j4 = job(4)
  val j5 = job(5)

  val f = for {
    f1 <- j1
    f2 <- j2
    f3 <- j3
    f4 <- j4
    f5 <- j5
  } yield List(f1, f2, f3, f4, f5)
  f.map(res => println(s"Done. ${res.size} jobs run"))
  Thread.sleep(6000) // We need to prevent main thread from quitting too early
}
于 2019-12-09T11:34:10.733 回答