scala future

Acceso al valor devuelto por Scala Futures



(5)

El caso del éxito (listInt) => Quiero devolver el listInt y no soy capaz de encontrar la manera de hacerlo.

La mejor práctica es que no devuelva el valor. En su lugar, simplemente pasa el futuro (o una versión transformada con map , flatMap , etc.) a todos los que necesitan este valor y pueden agregar su propio onComplete .

Si realmente necesita devolverlo (por ejemplo, al implementar un método heredado), lo único que puede hacer es bloquear (p. Ej., Con Await.result ) y debe decidir durante cuánto tiempo esperar.

Soy un novato en futuros de Scala y tengo una duda sobre el valor de retorno de los futuros de scala.

Entonces, generalmente la sintaxis para un futuro scala es

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

Quiero saber cómo acceder a la List[Int] desde algún otro método que llame a este método.

En otras palabras,

val result = downloadPage("localhost")

entonces, ¿cuál debería ser el enfoque para sacar a List[Int] del futuro?

He intentado utilizar el método del mapa, pero no he podido hacerlo con éxito.


Debes esperar a que el futuro se complete para obtener el resultado dado un intervalo de tiempo, aquí hay algo que funcionaría:

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)

Idealmente, si está utilizando un Future , no desea bloquear el hilo de ejecución, por lo que movería su lógica que trata el resultado de su Future al método de onComplete , algo como esto:

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


Espero que ya hayas resuelto esto desde que se me preguntó en 2013, pero tal vez mi respuesta puede ayudar a alguien más:

Si está utilizando Play Framework, admite Acciones asíncronas (en realidad, todas las acciones son asincrónicas dentro). Una forma fácil de crear una acción asíncrona es usar Action.async() . Debe proporcionar un Future[Result] a esta función.

Ahora puede hacer transformaciones desde su Future[List[Int]] a Future[Result] usando el mapa de Scala, flatMap, for-understanding o async / await. Aquí un ejemplo de la documentación de 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)) }


La mejor manera que he encontrado para pensar en un futuro es una caja que, en algún momento, contenga lo que desea. La clave con un futuro es que nunca se abre la caja. Intentar forzar la apertura de la caja te llevará a bloqueos y dolor. En cambio, colocas el futuro en otra caja más grande, generalmente usando el método del mapa.

Aquí hay un ejemplo de un futuro que contiene una cadena. Cuando el futuro se completa, se llama a 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) } } }

Tenga en cuenta que en este caso, estamos llamando al método principal y luego ... terminando. El futuro de la cadena, provisto por el ExecutionContext global, hace el trabajo de llamar a Console.println. Esto es genial, porque cuando cedemos el control sobre cuándo SomeString va a estar allí y cuándo se va a llamar a Console.println, dejamos que el sistema se administre solo. En contraste, mira lo que sucede cuando tratamos de forzar la caja abierta:

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

En este caso, tenemos que esperar, mantener un hilo moviendo los pulgares, hasta que recuperemos algo de String. Hemos abierto la caja, pero hemos tenido que requisar los recursos del sistema para lograrlo.


Puedes hacer algo como eso. Si el tiempo de espera que se da en el método Await.result es menor de lo que tarda en ejecutarse el awaitable , tendrá una TimeoutException y tendrá que manejar el error (o cualquier otro error).

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" } }