如何从scala Future的输出中获取价值?

时间:2019-04-08 10:12:11

标签: scala apache-spark

我正在尝试查询表,将查询的值存储在Scala Map中并返回同一张地图。 为此,我想出了以下代码:

def getBounds(incLogIdMap:scala.collection.mutable.Map[String, String]): Future[scala.collection.mutable.Map[String, String]] = Future {
  var boundsMap = scala.collection.mutable.Map[String, String]()
  incLogIdMap.keys.foreach(table => if(!incLogIdMap(table).contains("INVALID")) {
    val minMax    = s"select max(cast(to_char(update_tms,'yyyyddmmhhmmss') as bigint)) maxTms, min(cast(to_char(update_tms,'yyyyddmmhhmmss') as bigint)) minTms from queue.${table} where key_ids in (${incLogIdMap(table)})"
    val boundsDF  = spark.read.format("jdbc").option("url", commonParams.getGpConUrl()).option("dbtable", s"(${minMax}) as ctids")
      .option("user", commonParams.getGpUserName()).option("password", commonParams.getGpPwd()).load()
    val maxTms = boundsDF.select("minTms").head.getLong(0).toString + "," + boundsDF.select("maxTms").head.getLong(0).toString
    boundsMap += (table -> maxTms)
  }
  )
  boundsMap
}

为了从方法getBounds接收值,我使用了方法onCompletion,如下所示:

val tmsobj    = new MinMaxVals(spark, commonParams)
val boundsMap = tmsobj.getBounds(incLogIds)
boundsMap.onComplete({
  case Success(value) =>
  case Failure(value) =>
})

我以前在Scala中进行过编码,但是我刚接触过Scala中的Futures。谁能让我知道如何将getBounds返回的值检索到val boundsMap

2 个答案:

答案 0 :(得分:1)

您可以使用Awaits(不是最好的方法)

val boundsMap = Await.result(tmsobj.getBounds(incLogIds),Duration.Inf)

或者仅在需要时使用值

val boundsMap = tmsobj.getBounds(incLogIds)
booundsMap.map(value => Smth_To_Do(value))

答案 1 :(得分:1)

不建议从Future访问值,因为它违反了异步计算的目的。但是,在某些情况下,您可能正在处理旧代码,或者有些情况是从将来获取价值是前进的方向。为了解决这种情况,有两种方法

  1. 使用等待将阻塞线程
for  ... in

因此,这里等待的是,它将等待10秒以完成getBounds将来。如果它在此时间内完成,则您具有该值,否则将在此处获得异常。这种方法的最大缺点是,它会阻塞当前的执行线程。

  1. 使用以前使用的回调方法Await.result(getBounds, 10 seconds)
onComplete

所以onComplete要做的是注册一个回调函数,该函数将在将来完成时执行。这是比较安全的等待。 您可以参考Accessing value returned by scala futures了解更多详情。

我希望这能回答您的问题。