Scala Future monod 中的 onComplete 方法
Posted
技术标签:
【中文标题】Scala Future monod 中的 onComplete 方法【英文标题】:onComplete method in Scala's Fututre monod 【发布时间】: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)
【参考方案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)
【讨论】:
感谢维克托的详细解释!在我的示例中,我没有意识到最后两个语句的位置。当我交换他们的位置时,我得到了结果。以上是关于Scala Future monod 中的 onComplete 方法的主要内容,如果未能解决你的问题,请参考以下文章
Js Deferred/Promise/Future 与 Scala 等函数式语言相比
发现 scala 类型不匹配 Future[A] 预期 Future[B]