首页 文章

期货总是最终没有退货吗?

提问于
浏览
2

鉴于我们必须避免......

1)修改状态2)阻塞

...对于Future来说,什么是正确的端到端使用?

使用Futures的一般做法似乎是通过使用map,flatMap等将它们转换为其他Futures,但永远创造Futures并不好 .

是否总会在某处调用onComplete,方法是将Future的结果写入应用程序外部的某个位置(例如Web套接字;控制台;消息代理)或者是否存在访问结果的非阻塞方式?

关于Scaladocs中期货的所有信息 - http://docs.scala-lang.org/overviews/core/futures.html似乎最终写入控制台 . onComplete不会返回任何内容,所以我们不得不最终做一些"fire-and-forget" IO .

例如致电 println

f onComplete {
  case Success(number) => println(number)
  case Failure(err) => println("An error has occured: " + err.getMessage)
}

但是在更复杂的情况下,我们想要用未来的结果做更多的事情呢?

例如,在Play框架中,Action.async可以返回Future [Result],框架处理其余部分 . 它最终是否会期望永远不会从未来获得结果?

我们知道用户需要返回一个 Result ,那么框架如何只使用Unit方法来实现呢?

是否有一种非阻塞的方法来检索未来的 Value 并在应用程序的其他地方使用它,或者是对Await的调用是不可避免的?

4 回答

  • 0

    最佳做法是使用诸如 onCompleteonSuccessonFailure 之类的回调进行副作用操作,例如:记录,监控,I / O.

    如果您需要继续执行 Future 计算的结果而不是执行副作用操作,则应使用 map 来访问计算结果并对其进行组合 .

  • 1

    未来会返回一个单位,是的 . 那是因为它是一个异步触发器 . 您需要注册回调才能收集结果 .

    从你引用的scaladoc(带我的评论):

    // first assign the future with expected return type to a variable.
    val f: Future[List[String]] = Future {
      session.getRecentPosts
    }
    // immediately register the callbacks
    f onFailure {
      case t => println("An error has occurred: " + t.getMessage)
    }
    f onSuccess {
      case posts => for (post <- posts) println(post) 
    }
    

    或者不是打印,而是可以对结果做一些事情:

    f onSuccess {
      case posts: List[String] => someFunction(posts)
    }
    
  • 0

    试试这个:

    import scala.concurrent.duration._
    import scala.concurrent._
    import scala.concurrent.ExecutionContext.Implicits.global
    
    val f: Future[Int] = Future { 43 }
    
    val result: Int = Await.result(f, 0 nanos)
    

    那么这里发生了什么?

    您正在定义要在不同的 thread 上执行的计算 .

    所以你 Future { 43 } 立即返回 .

    然后你可以等待它并收集结果(通过 Await.result )或在其上定义计算而无需等待它完成(通过 map 等...)

  • 2

    实际上,你所谈论的那种未来用于副作用 . Future返回的结果取决于它的类型:

    val f = Future[Int] { 42 }
    

    例如,我可以将Future [Int]的结果发送给另一个Future:

    val f2 = f.flatMap(integer => Future{ println(integer) }) // may print 42
    

    如您所知,未来是一个同时发生的过程 . 所以你可以在将来得到它的结果(也就是说,使用诸如onComplete之类的方法)或者通过显式阻塞当前线程直到它获得一个值:

    import scala.concurrent.Await
    import akka.util.Timeout
    import scala.concurrent.duration._
    
    implicit val timeout = Timeout(5 seconds)
    val integer = Await.result(Future { 42 }, timeout.duration)
    

    通常,当您开始处理异步流程时,您必须考虑可能永远不会发生的反应 . 使用链式期货就像宣布可能随时可能被破坏的一系列事件 . 因此,等待Future的 Value 绝对不是一个好习惯,因为你可能永远不会得到它:

    val integer = Await.result(Future { throw new RuntimeException() }, timeout.duration) // will throw an uncaught exception
    

    尝试在事件方面考虑更多,而不是在程序方面 .

相关问题