Как извлечь значение из вывода Scala Future? - PullRequest
0 голосов
/ 08 апреля 2019

Я пытаюсь запросить таблицу, сохранить значения запроса в карте Scala и вернуть ту же карту.Для этого я придумал следующий код:

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, но я новичок в Futures в Scala.Может кто-нибудь сообщить мне, как я могу получить значение, возвращаемое getBounds в val boundsMap

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

Доступ к значению из Future не рекомендуется, так как это противоречит цели асинхронных вычислений.Однако могут быть случаи, когда вы имеете дело с унаследованным кодом, или некоторая ситуация, когда получение значения из будущего - это путь вперед.Чтобы справиться с такими ситуациями, есть два подхода:

  1. Использование await, которое заблокирует поток
Await.result(getBounds, 10 seconds)

Итак, что делает awaitбудет ждать 10 секунд, пока не завершится будущее getBounds.Если он завершится в течение этого времени, то у вас есть значение, иначе вы получите исключение здесь.Самый большой недостаток этого метода заключается в том, что он блокирует текущий поток выполнения.

Использование метода обратного вызова onComplete, как вы использовали
getBounds onComplete {
   case Success(someOption) => myMethod(someOption)
       case Failure(t) => println("Error)
     }

Так что onComplete делает, чтобы зарегистрировать функцию обратного вызова, которая будет выполняться всякий раз, когда будущеезавершено.Это сравнительно безопаснее, чем ждать.Вы можете обратиться к Доступ к значению, возвращаемому Scala Futures для получения более подробной информации.

Я надеюсь, что это ответ на ваш вопрос.

1 голос
/ 08 апреля 2019

Вы можете использовать Awaits (не лучший подход)

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

Или использовать значение только тогда, когда вам нужно

val boundsMap = tmsobj.getBounds(incLogIds)
booundsMap.map(value => Smth_To_Do(value))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...