Подтвердить что ты не робот

Доступ к стоимости, возвращаемой фьючерсами scala

Я новичок в фьючерсах scala, и у меня есть сомнения относительно возвращаемого значения фьючерсов scala.

Итак, в целом синтаксис для будущего scala -

 def downloadPage(url: URL) = Future[List[Int]] {

 }

Я хочу знать, как получить доступ к List[Int] из другого метода, который вызывает этот метод.

Другими словами,

val result = downloadPage("localhost") 

то каким должен быть подход, чтобы получить List[Int] из будущего?

Я попытался использовать метод карты, но не смог сделать это успешно.

4b9b3361

Ответ 1

Случай успеха (listInt) => Я хочу вернуть listInt, и я не могу понять, как это сделать.

Лучшая практика заключается в том, что вы не возвращаете значение. Вместо этого вы просто передаете будущее (или версию, преобразованную с map, flatMap и т.д.) flatMap, кому нужно это значение, и они могут добавить свое собственное onComplete.

Если вам действительно нужно вернуть его (например, при реализации устаревшего метода), то единственное, что вы можете сделать, - это заблокировать (например, с помощью Await.result), и вам нужно решить, как долго ждать.

Ответ 2

Вам нужно подождать, пока закончится будущее, чтобы получить результат, заданный несколько раз, вот что-то, что сработало бы:

  import scala.concurrent.duration._

  def downloadPage(url: URL) = Future[List[Int]] {
    List(1,2,3)
  }

  val result = downloadPage("localhost")

  val myListInt = result.result(10 seconds)

В идеале, если вы используете Future, вы не хотите блокировать исполняемый поток, поэтому вы переместите свою логику, которая связана с результатом вашего Future, в метод onComplete, что-то например:

  result.onComplete({
    case Success(listInt) => {
      //Do something with my list
    }
    case Failure(exception) => {
      //Do something with my error
    }
  })

Ответ 3

Я надеюсь, что вы уже решили это, так как он был задан в 2013 году, но, возможно, мой ответ может помочь кому-то еще:

Если вы используете Play Framework, он поддерживает async Actions (фактически все действия являются асинхронными внутри). Простым способом создания асинхронного действия является Action.async(). Вам необходимо предоставить Future[Result] для этой функции.

Теперь вы можете просто сделать преобразования с Future[List[Int]] до Future[Result] с помощью карты Scala, flatMap, для понимания или асинхронного/ждущего. Вот пример из документации Play Framework.

import play.api.libs.concurrent.Execution.Implicits.defaultContext

def index = Action.async {
  val futureInt = scala.concurrent.Future { intensiveComputation() }
  futureInt.map(i => Ok("Got result: " + i))
}

Ответ 4

Вы можете сделать что-то подобное. Если время ожидания, указанное в методе Await.result, меньше, чем для выполнения awaitable, у вас будет TimeoutException, и вам нужно обработать ошибку (или любую другую ошибку).

import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{Try, Success, Failure}
import scala.concurrent.duration._

object MyObject {
    def main(args: Array[String]) {

        val myVal: Future[String] = Future { silly() }

        // values less than 5 seconds will go to 
        // Failure case, because silly() will not be done yet
        Try(Await.result(myVal, 10 seconds)) match {
            case Success(extractedVal) => { println("Success Happened: " + extractedVal) }
            case Failure(_) => { println("Failure Happened") }
            case _ => { println("Very Strange") }
        }      
    }

    def silly(): String = {
        Thread.sleep(5000)
        "Hello from silly"
        }
}

Ответ 5

Лучший способ, которым Айв подумал о будущем, - это коробка, которая в какой-то момент будет содержать то, что вы хотите. Главное в будущем - это то, что вы никогда не открываете коробку. Попытка заставить открыть коробку приведет вас к блокированию и печали. Вместо этого вы помещаете Будущее в другой, более крупный ящик, обычно используя метод карты.

Вот пример будущего, который содержит строку. Когда будущее завершается, Console.println вызывается:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object Main {

  def main(args:Array[String]) : Unit = {
    val stringFuture: Future[String] = Future.successful("hello world!")
    stringFuture.map {
      someString =>
        // if you use .foreach you avoid creating an extra Future, but we are proving
        // the concept here...
        Console.println(someString)
    }
  }
}

Обратите внимание, что в этом случае вызывается основной метод, а затем... завершение. Строки Future, предоставляемые глобальным ExecutionContext, выполняют работу при вызове Console.println. Это здорово, потому что, когда мы отказываемся от контроля над тем, когда someString будет там, и когда Console.println будет вызван, мы позволяем системе управлять собой. В принципе, посмотрите, что происходит, когда мы пытаемся открыть окно:

val stringFuture: Future[String] = Future.successful("hello world!")
val someString = Future.await(stringFuture)

В этом случае нам нужно подождать - держите нить, крутящую большие пальцы, - пока мы не вернем someString. Мы открыли коробку, но нам пришлось командовать системными ресурсами, чтобы добраться до нее.