【问题标题】:onComplete method in Scala's Fututre monodScala Future monod 中的 onComplete 方法
【发布时间】:2021-05-30 16:40:27
【问题描述】:

我正在学习 Scala 中的 Future 并拥有以下代码 sn-p。我正在根据名称中的第一个字母生成随机标记。 对于以下场景,我希望通过onComplete 方法打印一个列表。但它不打印任何东西。

def randomMark(name:String) = name(0) match {
  case 'R'|'A'|'J'|'S' => Thread.sleep(500); 99
  case  _              => Thread.sleep(500); 80
}

import scala.concurrent._
import concurrent.ExecutionContext.Implicits.global

val returns = Future sequence List( Future(randomMark("Rob")), Future(randomMark("Andy")), Future(randomMark("George")) )
    
Thread.sleep(550)

returns onComplete { e => { val y1 = e.getOrElse("Error"); println(y1) } }    
//This println statement does not execute. I expect a list List(99,99,80) to be printed

有人可以帮我理解为什么我为onComplete 方法提供的功能文字不执行吗?

谢谢!

【问题讨论】:

  • 如果这是一个完整的程序,那么它会直接退出而不等待未来完成。尝试添加Await.ready(returns, Duration.Inf)

标签: scala future


【解决方案1】:

很可能是因为您需要等待结果,因为onComplete 是一个异步操作。

import scala.concurrent.duration._
import scala.concurrent._

def randomMark(name:String) = name(0) match {
  case 'R'|'A'|'J'|'S' => Thread.sleep(500); 99
  case  _              => Thread.sleep(500); 80
}

import scala.concurrent._
import concurrent.ExecutionContext.Implicits.global

val returns = Future sequence List( Future(randomMark("Rob")), Future(randomMark("Andy")), Future(randomMark("George")) )
    
Thread.sleep(550)

returns onComplete { e => { val y1 = e.getOrElse("Error"); println(y1) } }   
println("Waiting futures to be completed")
Await.ready(returns, 5.seconds)
println("Futures to be completed")

打印出来了:

Waiting futures to be completed
List(99, 99, 80)
Futures to be completed

斯卡蒂:https://scastie.scala-lang.org/SWv18p8RTtuo7nMNHNHMoQ

【讨论】:

  • 谢谢伊万!当我交换程序中的最后两个语句时,我得到了预期的结果。感谢您的宝贵时间。
【解决方案2】:

由于回调是异步执行的,因此您需要在程序退出之前等待回调完成。在这种情况下,如果你想等待一个 onComplete 回调,你需要以某种方式发出它的完成信号。在以下示例中,我使用了 Promise:

def randomMark(name:String) = name(0) match {
  case 'R'|'A'|'J'|'S' => Thread.sleep(500); 99
  case  _              => Thread.sleep(500); 80
}

import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global

val returns = Future sequence List( Future(randomMark("Rob")), Future(randomMark("Andy")), Future(randomMark("George")) )
val returns: scala.concurrent.Future[List[Int]] = Future(<not completed>)

val p = Promise[Unit]()

returns onComplete { e => { val y1 = e.getOrElse("Error"); println(y1); p.success(()) } }

Await.ready(p.future, 5.seconds)

但是,您可以改用 andThen,如下所示:

def randomMark(name:String) = name(0) match {
  case 'R'|'A'|'J'|'S' => Thread.sleep(500); 99
  case  _              => Thread.sleep(500); 80
}

import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global

val returns = 
  Future sequence List( Future(randomMark("Rob")), Future(randomMark("Andy")), Future(randomMark("George")) ) andThen
  { case e => { val y1 = e.getOrElse("Error"); println(y1) } }

Await.ready(returns, 5.seconds)

【讨论】:

  • 感谢维克托的详细解释!在我的示例中,我没有意识到最后两个语句的位置。当我交换他们的位置时,我得到了结果。
猜你喜欢
  • 1970-01-01
  • 2017-08-01
  • 2019-09-16
  • 2017-04-20
  • 1970-01-01
  • 2014-05-22
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
相关资源
最近更新 更多