0
votes

I am newbie to scala . I have a def which returns Future[Option[String]]. I have to return Option[String]] from that def. I cannot use Await.result. Any other alternatives

def processJson(key: String, value:String) : Future[Option[String]]{
}

I have gone through this link but could not figure.

http://allaboutscala.com/tutorials/chapter-9-beginner-tutorial-using-scala-futures/#method-future-return-type

Any help please

3
Does this answer your question? Accessing value returned by scala futuresDuelist
Can you explain more of your problem? Why you have a Future at all? Why you need to just return a plain Option? Why you can not Await?Luis Miguel Mejía Suárez

3 Answers

1
votes

I think you can either pass the Future without waiting for its completion (the calling method will deal with it) or you can call Await.result (but you said it isn't an option).

Anyway, I don't think you should return a Future if you don't want do deal with it, also just to process some JSON object (and not, for istance, to retrieve something from a remote server).

1
votes

You can either:

  1. Await them (see here for demo):
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def returnsAFuture: Future[Int] = Future {
  Thread.sleep(1000)
  10
}

import scala.concurrent.Await
import scala.concurrent.duration._
println(Await.result(returnsAFuture, Duration.Inf))
  1. Sleep the thread for a specific period of time (see here for demo - based on the post you linked to):
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def returnsAFuture: Future[Int] = Future {
  Thread.sleep(1000)
  10
}

import scala.util.Success
returnsAFuture.onComplete {
  case Success(value) => println(value)
  case _ => println("No value found")
}

Thread.sleep(2000)
  1. Leave the Future alone and deal with it later by mapping inside it (see here for demo):
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def returnsAFuture: Future[Int] = Future {
  Thread.sleep(1000)
  10
}

val aNewFuture = returnsAFuture.map {_ * 2}

// do some other stuff

// access the result of the Future only when you absolutely have to

import scala.concurrent.Await
import scala.concurrent.duration._
println(Await.result(aNewFuture, Duration.Inf))

The whole point of a Future is that you can deal with it under the assumption that it will resolve successfully by leaving it as a Future for as long as you can and dealing with any exceptions thrown at the last possible moment.

If you are using a framework like Play, you can just return a Future at the end and Play will resolve it for you. If not though, you will need to wait for the Future to finish at some point.

I would recommend doing option 3 though, so you can leave this until the last moment and not block your Thread unnecessarily early.

0
votes

Probably when you are using futures, you shall await but there are rare such cases like that, because usually when you use futures you have a continuous running application so you would simply choose to use transformers (map, flatmap, for expressions) or consumers (foreach, onComplete) etc