0
votes

Im having an issue to extract string value from a Future[JsValue]

I tried Map and Flatmap but i guess im doing somthing wrong...

I have this method that return Future[JsValue]

 val chunk: Future[JsValue] = BusinessLogic.Methods.getJsonValue(url)

If i was map i get a Future[String]

 val next: Future[String] = (chunk.map(_.\("paging").\("next").as[String]))

If i use flat map i get type mismatch

 val next = chunk.flatMap(x=>x.\("paging").\("next").as[String])

What will be the correct way to extract the value ??

thanks

2
What do you mean extract the value? If you want to unwrap the future you have to block (and depending on what are you trying to do it can be a bad idea). map wraps the result of the anonymous function in another future, flatMap instead needs you to wrap the result in a future, in both cases the return type is Future[T]. - Ende Neu
I have to get the string value out of the future in order to pass it to another method that tack a string - MIkCode
next.map(otherFunctionThatTakesAString) - Ryan

2 Answers

0
votes

http://docs.scala-lang.org/overviews/core/futures.html

From oficial tutorials, regarding map:

One of the basic combinators is map, which, given a future and a mapping function for the value of the future, produces a new future that is completed with the mapped value once the original future is successfully completed.

Regarding flat map.

The flatMap method takes a function that maps the value to a new future g, and then returns a future which is completed once g is completed.

So in your case since you just want to convert response to some other value, you need a map function, which would map result of your future to String.

val next: Future[String] = (chunk.map(_.\("paging").\("next").as[String]))

Next value here is a either failure from chunk or result of mapping chunk js value to String.

If you would have some additional asynchronous calculations, like

def calculations: (x: String): Future[Int] = ...

val next: Future[Int] = chunk.flatMap(js=> {
   val x = js.\("paging").\("next").as[String]
   calculations(x)
})

You would need to use flatMap, combining two dependent asynchronous futures in one. Next value here is a result of calculations function, applied to result returned from chunk.

0
votes

If you want to unwrap your Future you have to block. This is a very bad idea and should be avoided if possible!

def nextFunction(s:String):Unit = ???
val chunk: Future[JsValue] = BusinessLogic.Methods.getJsonValue(url)
val next: String = Await.result(chunk, 1.second)
nextFunction(next)

As mentioned above this is a bad idea! The better solution would be:

def nextFunction(s:String):Unit = ???
val chunk: Future[JsValue] = BusinessLogic.Methods.getJsonValue(url)
chunk.foreach(nextFunction)

This basically calls the nextFunction with the value as soon as it is available and we never have to block.